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.graphics.Canvas; 21 import android.graphics.Paint; 22 import android.graphics.Paint.Style; 23 import android.util.AttributeSet; 24 import android.widget.Button; 25 import android.view.View.OnClickListener; 26 import android.view.View; 27 import android.view.MotionEvent; 28 import android.content.res.Resources; 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 calc.adjustFontSize(this); 68 } 69 70 71 @Override 72 public void onSizeChanged(int w, int h, int oldW, int oldH) { 73 measureText(); 74 } 75 76 private void measureText() { 77 Paint paint = getPaint(); 78 mTextX = (getWidth() - paint.measureText(getText().toString())) / 2; 79 mTextY = (getHeight() - paint.ascent() - paint.descent()) / 2; 80 } 81 82 @Override 83 protected void onTextChanged(CharSequence text, int start, int before, int after) { 84 measureText(); 85 } 86 87 private void drawMagicFlame(int duration, Canvas canvas) { 88 int alpha = 255 - 255 * duration / CLICK_FEEDBACK_DURATION; 89 int color = CLICK_FEEDBACK_COLOR | (alpha << 24); 90 91 mFeedbackPaint.setColor(color); 92 canvas.drawRect(1, 1, getWidth() - 1, getHeight() - 1, mFeedbackPaint); 93 } 94 95 @Override 96 public void onDraw(Canvas canvas) { 97 if (mAnimStart != -1) { 98 int animDuration = (int) (System.currentTimeMillis() - mAnimStart); 99 100 if (animDuration >= CLICK_FEEDBACK_DURATION) { 101 mAnimStart = -1; 102 } else { 103 drawMagicFlame(animDuration, canvas); 104 postInvalidateDelayed(CLICK_FEEDBACK_INTERVAL); 105 } 106 } else if (isPressed()) { 107 drawMagicFlame(0, canvas); 108 } 109 110 CharSequence text = getText(); 111 canvas.drawText(text, 0, text.length(), mTextX, mTextY, getPaint()); 112 } 113 114 public void animateClickFeedback() { 115 mAnimStart = System.currentTimeMillis(); 116 invalidate(); 117 } 118 119 @Override 120 public boolean onTouchEvent(MotionEvent event) { 121 boolean result = super.onTouchEvent(event); 122 123 switch (event.getAction()) { 124 case MotionEvent.ACTION_UP: 125 animateClickFeedback(); 126 break; 127 case MotionEvent.ACTION_DOWN: 128 case MotionEvent.ACTION_CANCEL: 129 invalidate(); 130 break; 131 } 132 133 return result; 134 } 135 } 136