1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.calculator2; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.graphics.Canvas; 22 import android.graphics.Paint; 23 import android.graphics.Paint.Style; 24 import android.util.AttributeSet; 25 import android.view.View.OnClickListener; 26 import android.view.View; 27 import android.view.MotionEvent; 28 import android.widget.Button; 29 30 /** 31 * Button with click-animation effect. 32 */ 33 class ColorButton extends Button implements OnClickListener { 34 int CLICK_FEEDBACK_COLOR; 35 static final int CLICK_FEEDBACK_INTERVAL = 10; 36 static final int CLICK_FEEDBACK_DURATION = 350; 37 38 float mTextX; 39 float mTextY; 40 long mAnimStart; 41 OnClickListener mListener; 42 Paint mFeedbackPaint; 43 44 public ColorButton(Context context, AttributeSet attrs) { 45 super(context, attrs); 46 Calculator calc = (Calculator) context; 47 init(calc); 48 mListener = calc.mListener; 49 setOnClickListener(this); 50 } 51 52 public void onClick(View view) { 53 mListener.onClick(this); 54 } 55 56 private void init(Calculator calc) { 57 Resources res = getResources(); 58 59 CLICK_FEEDBACK_COLOR = res.getColor(R.color.magic_flame); 60 mFeedbackPaint = new Paint(); 61 mFeedbackPaint.setStyle(Style.STROKE); 62 mFeedbackPaint.setStrokeWidth(2); 63 getPaint().setColor(res.getColor(R.color.button_text)); 64 65 mAnimStart = -1; 66 } 67 68 69 @Override 70 public void onSizeChanged(int w, int h, int oldW, int oldH) { 71 measureText(); 72 } 73 74 private void measureText() { 75 Paint paint = getPaint(); 76 mTextX = (getWidth() - paint.measureText(getText().toString())) / 2; 77 mTextY = (getHeight() - paint.ascent() - paint.descent()) / 2; 78 } 79 80 @Override 81 protected void onTextChanged(CharSequence text, int start, int before, int after) { 82 measureText(); 83 } 84 85 private void drawMagicFlame(int duration, Canvas canvas) { 86 int alpha = 255 - 255 * duration / CLICK_FEEDBACK_DURATION; 87 int color = CLICK_FEEDBACK_COLOR | (alpha << 24); 88 89 mFeedbackPaint.setColor(color); 90 canvas.drawRect(1, 1, getWidth() - 1, getHeight() - 1, mFeedbackPaint); 91 } 92 93 @Override 94 public void onDraw(Canvas canvas) { 95 if (mAnimStart != -1) { 96 int animDuration = (int) (System.currentTimeMillis() - mAnimStart); 97 98 if (animDuration >= CLICK_FEEDBACK_DURATION) { 99 mAnimStart = -1; 100 } else { 101 drawMagicFlame(animDuration, canvas); 102 postInvalidateDelayed(CLICK_FEEDBACK_INTERVAL); 103 } 104 } else if (isPressed()) { 105 drawMagicFlame(0, canvas); 106 } 107 108 CharSequence text = getText(); 109 canvas.drawText(text, 0, text.length(), mTextX, mTextY, getPaint()); 110 } 111 112 public void animateClickFeedback() { 113 mAnimStart = System.currentTimeMillis(); 114 invalidate(); 115 } 116 117 @Override 118 public boolean onTouchEvent(MotionEvent event) { 119 boolean result = super.onTouchEvent(event); 120 121 switch (event.getAction()) { 122 case MotionEvent.ACTION_UP: 123 if (isPressed()) { 124 animateClickFeedback(); 125 } else { 126 invalidate(); 127 } 128 break; 129 case MotionEvent.ACTION_DOWN: 130 case MotionEvent.ACTION_CANCEL: 131 mAnimStart = -1; 132 invalidate(); 133 break; 134 } 135 136 return result; 137 } 138 } 139