Android自訂圓形按鈕點擊進度動畫,android自訂
一個月前我去面試的時候被人問到一個類似的問題,當時沒答上來,一回家找了下資料:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0325/1603.html,
根據上面連結,我自己改了下半小時後實現了比較粗糙的效果,如,不太好見諒哈~
具體分解成4個部分:
底部一個灰色的空心描邊圈,中間一個文字,2邊各一個半圓來做向上的動畫;
具體代碼:
public class CircleBarTwoSider extends View { private RectF mColorWheelRectangle = new RectF();//圓圈的矩形範圍 private Paint mDefaultWheelPaint; //繪製底部灰色圓圈的畫筆 private Paint mColorWheelPaintLeft; //繪製藍色扇形的畫筆 左邊的 private Paint mColorWheelPaintRight; //繪製藍色扇形的畫筆 右邊的 private Paint textPaint; //中間文字的畫筆 private float mColorWheelRadius; //圓圈普通狀態下的半徑 private float circleStrokeWidth; //圓圈的線條寬度 private float pressExtraStrokeWidth;//按下狀態下增加的圓圈線條增加的粗細 private String mText;//中間文字內容 private int mCount; //為了達到數字增加效果而添加的變數,他和mText其實代表一個意思 private float mSweepAnglePer; //為了達到藍色扇形增加效果而添加的變數,他和mSweepAngle其實代表一個意思 private float mSweepAngle; //扇形弧度 private int mTextSize;//文字顏色 BarAnimation anim;//動畫類 private int TIME = 300; public CircleBarTwoSider(Context context) { super(context); init(null, 0); } public CircleBarTwoSider(Context context, AttributeSet attrs) { super(context, attrs); init(attrs, 0); } public CircleBarTwoSider(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(attrs, defStyle); } private void init(AttributeSet attrs, int defStyle) { circleStrokeWidth = MyUtils.dip2px(getContext(), 10); pressExtraStrokeWidth = MyUtils.dip2px(getContext(), 2); mTextSize = MyUtils.dip2px(getContext(), 20); mColorWheelPaintRight = new Paint(Paint.ANTI_ALIAS_FLAG); mColorWheelPaintRight.setColor(0xFF29a6f6); mColorWheelPaintRight.setStyle(Paint.Style.STROKE); mColorWheelPaintRight.setStrokeMiter(0);// mColorWheelPaintRight.setStrokeCap(Paint.Cap.ROUND);//開啟顯示邊緣為圓形 mColorWheelPaintRight.setStrokeWidth(circleStrokeWidth); mColorWheelPaintLeft = new Paint(Paint.ANTI_ALIAS_FLAG); mColorWheelPaintLeft.setColor(0xFF29a6f6); mColorWheelPaintLeft.setStyle(Paint.Style.STROKE); mColorWheelPaintLeft.setStrokeMiter(0);// mColorWheelPaintLeft.setStrokeCap(Paint.Cap.ROUND);//開啟顯示邊緣為圓形 mColorWheelPaintLeft.setStrokeWidth(circleStrokeWidth); mDefaultWheelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mDefaultWheelPaint.setColor(0xFFeeefef); mDefaultWheelPaint.setStyle(Paint.Style.STROKE); mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth); textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); textPaint.setColor(0xFF333333); textPaint.setStyle(Style.FILL_AND_STROKE); textPaint.setTextAlign(Align.LEFT); textPaint.setTextSize(mTextSize); mText = "0"; mSweepAngle = 1; anim = new BarAnimation(); anim.setDuration(TIME);//設定動畫時常 } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); canvas.drawArc(mColorWheelRectangle, -90, 360, false, mDefaultWheelPaint); canvas.drawArc(mColorWheelRectangle, 90, mSweepAnglePer, false, mColorWheelPaintRight); canvas.drawArc(mColorWheelRectangle, 90, -mSweepAnglePer, false, mColorWheelPaintLeft); Rect bounds = new Rect(); String textstr="可以買:"+mCount+""; textPaint.getTextBounds(textstr, 0, textstr.length(), bounds); canvas.drawText(textstr+"", (mColorWheelRectangle.centerX()) - (textPaint.measureText(textstr) / 2), mColorWheelRectangle.centerY() + bounds.height() / 2,textPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); int min = Math.min(width, height); setMeasuredDimension(min, min); mColorWheelRadius = min - circleStrokeWidth -pressExtraStrokeWidth ; mColorWheelRectangle.set(circleStrokeWidth+pressExtraStrokeWidth, circleStrokeWidth+pressExtraStrokeWidth, mColorWheelRadius, mColorWheelRadius); } @Override public void setPressed(boolean pressed) { // TODO Auto-generated method stub Log.i("hloong","call setPressed "); if (pressed) { mColorWheelPaintLeft.setColor(0xFF165da6); mColorWheelPaintRight.setColor(0xFF165da6); textPaint.setColor(0xFF070707); mColorWheelPaintLeft.setStrokeWidth(circleStrokeWidth+pressExtraStrokeWidth); mColorWheelPaintRight.setStrokeWidth(circleStrokeWidth+pressExtraStrokeWidth); mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth+pressExtraStrokeWidth); textPaint.setTextSize(mTextSize-pressExtraStrokeWidth); } else { mColorWheelPaintLeft.setColor(0xFF29a6f6); mColorWheelPaintRight.setColor(0xFF29a6f6); textPaint.setColor(0xFF333333); mColorWheelPaintLeft.setStrokeWidth(circleStrokeWidth); mColorWheelPaintRight.setStrokeWidth(circleStrokeWidth); mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth); textPaint.setTextSize(mTextSize); } super.setPressed(pressed); this.invalidate(); } public void startCustomAnimation(){ this.startAnimation(anim); } public void setText(String text){ mText = text; this.startAnimation(anim); } public void setSweepAngle(float sweepAngle){ mSweepAngle = sweepAngle; } /** * 動畫 * @author long * 2015-3-20下午2:11:22 */ public class BarAnimation extends Animation { /** * Initializes expand collapse animation, has two types, collapse (1) and expand (0). * @param view The view to animate * @param type The type of animation: 0 will expand from gone and 0 size to visible and layout size defined in xml. * 1 will collapse view and set to gone * 動畫類利用了applyTransformation參數中的interpolatedTime參數(從0到1)的變化特點, * 實現了該View的某個屬性隨時間改變而改變。原理是在每次系統調用animation的applyTransformation()方法時, * 改變mSweepAnglePer,mCount的值, * 然後調用postInvalidate()不停的繪製view。 */ public BarAnimation() { } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); //mSweepAnglePer,mCount這兩個屬性只是動畫過程中要用到的臨時屬性, //mText和mSweepAngle才是動畫結束之後表示扇形弧度和中間數值的真實值。 if (interpolatedTime < 1.0f) { mSweepAnglePer = interpolatedTime * mSweepAngle; mCount = (int)(interpolatedTime * Float.parseFloat(mText)); } else { mSweepAnglePer = mSweepAngle; mCount = Integer.parseInt(mText); } postInvalidate(); } }}
Activity的代碼:
public class MainActivity extends Activity { private CircleBarTwoSider circleBar; private CircleBar circleBar2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); circleBar = (CircleBarTwoSider) findViewById(R.id.circle); circleBar.setSweepAngle(120);//設定角度 circleBar.setText("27000"); circleBar.setOnClickListener(new OnClickListener(){ @Override public void onClick(View view){ circleBar.startCustomAnimation(); } }); circleBar2 = (CircleBar) findViewById(R.id.circle2); circleBar2.setSweepAngle(120); circleBar2.setText("500"); circleBar2.setOnClickListener(new OnClickListener(){ @Override public void onClick(View view){ circleBar2.startCustomAnimation(); } }); }}
項目:https://github.com/hloong/CricleBarDemo