首页 > 代码库 > Android自定义View之倒计时Countdown实现
Android自定义View之倒计时Countdown实现
先看一下效果:
在点击OK键之后,开始倒计时。
实现步骤
1、新建Android工程"CountdownView"
2、自定义Drawable
自定义View并没有直接的用户交互,简化起见,可以自定义实现一个drawable,作为ImageView的背景
观察一下View的构成,分为几个部分:
1. 外围圆环边界
2. 进度条
3. 内部圆形背景
4. 倒计时数字
另外,要画出这几个部分,画笔Paint肯定少不了
好了,自定义一个“CountdownDrawable”继承Drawable
1 public class CountdownDrawable extends Drawable { 2 3 //画笔 4 private Paint mPaint; 5 private RectF mArcRect; 6 7 //当前进度条进度 8 private float progress; 9 //边框圆颜色10 private int outlineColor;11 //内部背景圆颜色12 private int innerColor;13 //进度条颜色14 private int ringColor;15 //进度条宽度16 private int ringWidth;17 //倒计时数字18 private int showNumber;19 //数字颜色20 private int textColor;21 22 @Override23 public void draw(Canvas canvas) {24 // TODO Auto-generated method stub25 26 }27 28 @Override29 public void setAlpha(int alpha) {30 mPaint.setAlpha(alpha);31 }32 33 @Override34 public void setColorFilter(ColorFilter cf) {35 }36 37 @Override38 public int getOpacity() {39 return mPaint.getAlpha();40 }41 42 }
变量初始化:
1 public CountdownDrawable(int ringWidth, int outlineColor, int innerColor, int ringColor, int showNumber, int textColor) { 2 mPaint = new Paint(); 3 mArcRect = new RectF(); 4 5 this.outlineColor = outlineColor; 6 this.innerColor = innerColor; 7 this.ringColor = ringColor; 8 this.ringWidth = ringWidth; 9 this.showNumber = showNumber;10 this.textColor = textColor;11 }
3、 实现draw方法
1 public void draw(Canvas canvas) { 2 //获取view的边界 3 final Rect bounds = getBounds(); 4 5 int size = bounds.height() > bounds.width() ? bounds.width() : bounds.height(); 6 float outerRadius = ((size / 2) * 0.75f) * 0.937f; 7 float innerRadius = ((size / 2) * 0.75f) * 0.75f; 8 float offsetX = (bounds.width() - outerRadius * 2) / 2; 9 float offsetY = (bounds.height() - outerRadius * 2) / 2;10 11 //画边框圆12 mPaint.setStyle(Paint.Style.STROKE);13 mPaint.setStrokeWidth(1);14 mPaint.setColor(outlineColor);15 canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius, mPaint);16 17 //画内部背景18 mPaint.setStyle(Paint.Style.FILL);19 mPaint.setColor(innerColor);20 canvas.drawCircle(bounds.centerX(), bounds.centerY(), innerRadius, mPaint);21 22 //画倒计时数字23 float textSize = innerRadius * 2 * 0.75f;24 mPaint.setTextSize(textSize);25 mPaint.setTextAlign(Align.CENTER);26 mPaint.setColor(textColor);27 float textX = bounds.centerX();28 float textY = bounds.centerY() - (mPaint.descent() + mPaint.ascent()) / 2; 29 canvas.drawText(Integer.toString(showNumber), textX, textY, mPaint);30 31 //画进度条32 int halfRingWidth = ringWidth / 2;33 float arcX0 = offsetX + halfRingWidth;34 float arcY0 = offsetY + halfRingWidth;35 float arcX = offsetX + outerRadius * 2 - halfRingWidth;36 float arcY = offsetY + outerRadius * 2 - halfRingWidth;37 38 mPaint.setColor(ringColor);39 mPaint.setStyle(Paint.Style.STROKE);40 mPaint.setStrokeWidth(ringWidth);41 mPaint.setStrokeCap(Paint.Cap.ROUND);42 mArcRect.set(arcX0, arcY0, arcX, arcY);43 canvas.drawArc(mArcRect, 89, progress, false, mPaint);44 }
4、 设置进度条及倒计时数字
1 public float getProgress() { 2 return progress / PROGRESS_FACTOR; 3 } 4 5 public void setProgress(float progress) { 6 this.progress = progress * PROGRESS_FACTOR; 7 8 invalidateSelf(); 9 }10 11 public int getShowNumber() {12 return showNumber;13 }14 15 public void setShowNumber(int showNumber) {16 this.showNumber = showNumber;17 18 invalidateSelf();19 }
5、 在Activity中完成drawable的使用
首先定义一个ImageView,设置其图片为刚刚定义的drawable
1 mIv = (ImageView)findViewById(R.id.iv);2 mCdDrawable = new CountdownDrawable(getResources().getDimensionPixelSize(R.dimen.drawable_ring_size), getResources().getColor(R.color.dark_grey), getResources().getColor(R.color.brightly_grey)3 , getResources().getColor(R.color.holo_green_light), 5, getResources().getColor(R.color.red));4 mIv.setImageDrawable(mCdDrawable);
各颜色定义如下:
1 <dimen name="drawable_ring_size">4dp</dimen>2 3 <color name="dark_grey">#FF54585A</color>4 <color name="holo_green_light">#FF99CC00</color>5 <color name="brightly_grey">#CF9EA2A2</color>6 <color name="red">#FFE61E27</color>
使用属性动画,计算进度条progress及倒计时数字showNumber
1 private Animator prepareAnimator() { 2 AnimatorSet animation = new AnimatorSet(); 3 4 // 进度条动画 5 ObjectAnimator progressAnimator = ObjectAnimator.ofFloat(mCdDrawable, "progress", 1f, 0f); 6 progressAnimator.setDuration(5000); 7 progressAnimator.setInterpolator(new LinearInterpolator()); 8 progressAnimator.addListener(new Animator.AnimatorListener() { 9 10 @Override11 public void onAnimationStart(Animator animation) {12 13 }14 15 @Override16 public void onAnimationRepeat(Animator animation) {17 18 }19 20 @Override21 public void onAnimationEnd(Animator animation) {22 mIv.setVisibility(View.GONE);23 }24 25 @Override26 public void onAnimationCancel(Animator animation) {27 mIv.setVisibility(View.GONE);28 }29 });30 31 // 居中的倒计时数字32 ObjectAnimator showNumberAnimator = ObjectAnimator.ofInt(mCdDrawable, "showNumber", 5, 0);33 showNumberAnimator.setDuration(5000);34 showNumberAnimator.setInterpolator(new LinearInterpolator());35 36 animation.playTogether(progressAnimator, showNumberAnimator);37 return animation;38 }
最后在button中添加点击事件
1 private View.OnClickListener mBtnOnClickListener = new View.OnClickListener() { 2 3 @Override 4 public void onClick(View v) { 5 if(mAnimator != null) { 6 mAnimator.cancel(); 7 } 8 mIv.setVisibility(View.VISIBLE); 9 mAnimator = prepareAnimator();10 mAnimator.start();11 }12 };
完整工程代码放到了github上
Android自定义View之倒计时Countdown实现
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。