先看一下效果:
在点击OK键之后,开始倒计时。
实现步骤
1、新建Android工程"CountdownView"
2、自定义Drawable
自定义View并没有直接的用户交互,简化起见,可以自定义实现一个drawable,作为ImageView的背景
观察一下View的构成,分为几个部分:
1. 外围圆环边界
2. 进度条
3. 内部圆形背景
4. 倒计时数字
另外,要画出这几个部分,画笔Paint肯定少不了
好了,自定义一个“CountdownDrawable”继承Drawable
public class CountdownDrawable extends Drawable { //画笔
private Paint mPaint;
private RectF mArcRect; //当前进度条进度
private float progress;
//边框圆颜色
private int outlineColor;
//内部背景圆颜色
private int innerColor;
//进度条颜色
private int ringColor;
//进度条宽度
private int ringWidth;
//倒计时数字
private int showNumber;
//数字颜色
private int textColor; @Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub } @Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
} @Override
public void setColorFilter(ColorFilter cf) {
} @Override
public int getOpacity() {
return mPaint.getAlpha();
} }
变量初始化:
public CountdownDrawable(int ringWidth, int outlineColor, int innerColor, int ringColor, int showNumber, int textColor) {
mPaint = new Paint();
mArcRect = new RectF(); this.outlineColor = outlineColor;
this.innerColor = innerColor;
this.ringColor = ringColor;
this.ringWidth = ringWidth;
this.showNumber = showNumber;
this.textColor = textColor;
}
3、 实现draw方法
public void draw(Canvas canvas) {
//获取view的边界
final Rect bounds = getBounds(); int size = bounds.height() > bounds.width() ? bounds.width() : bounds.height();
float outerRadius = ((size / 2) * 0.75f) * 0.937f;
float innerRadius = ((size / 2) * 0.75f) * 0.75f;
float offsetX = (bounds.width() - outerRadius * 2) / 2;
float offsetY = (bounds.height() - outerRadius * 2) / 2; //画边框圆
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(1);
mPaint.setColor(outlineColor);
canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius, mPaint); //画内部背景
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(innerColor);
canvas.drawCircle(bounds.centerX(), bounds.centerY(), innerRadius, mPaint); //画倒计时数字
float textSize = innerRadius * 2 * 0.75f;
mPaint.setTextSize(textSize);
mPaint.setTextAlign(Align.CENTER);
mPaint.setColor(textColor);
float textX = bounds.centerX();
float textY = bounds.centerY() - (mPaint.descent() + mPaint.ascent()) / 2;
canvas.drawText(Integer.toString(showNumber), textX, textY, mPaint); //画进度条
int halfRingWidth = ringWidth / 2;
float arcX0 = offsetX + halfRingWidth;
float arcY0 = offsetY + halfRingWidth;
float arcX = offsetX + outerRadius * 2 - halfRingWidth;
float arcY = offsetY + outerRadius * 2 - halfRingWidth; mPaint.setColor(ringColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(ringWidth);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mArcRect.set(arcX0, arcY0, arcX, arcY);
canvas.drawArc(mArcRect, 89, progress, false, mPaint);
}
4、 设置进度条及倒计时数字
public float getProgress() {
return progress / PROGRESS_FACTOR;
} public void setProgress(float progress) {
this.progress = progress * PROGRESS_FACTOR; invalidateSelf();
} public int getShowNumber() {
return showNumber;
} public void setShowNumber(int showNumber) {
this.showNumber = showNumber; invalidateSelf();
}
5、 在Activity中完成drawable的使用
首先定义一个ImageView,设置其图片为刚刚定义的drawable
mIv = (ImageView)findViewById(R.id.iv);
mCdDrawable = new CountdownDrawable(getResources().getDimensionPixelSize(R.dimen.drawable_ring_size), getResources().getColor(R.color.dark_grey), getResources().getColor(R.color.brightly_grey)
, getResources().getColor(R.color.holo_green_light), 5, getResources().getColor(R.color.red));
mIv.setImageDrawable(mCdDrawable);
各颜色定义如下:
<dimen name="drawable_ring_size">4dp</dimen> <color name="dark_grey">#FF54585A</color>
<color name="holo_green_light">#FF99CC00</color>
<color name="brightly_grey">#CF9EA2A2</color>
<color name="red">#FFE61E27</color>
使用属性动画,计算进度条progress及倒计时数字showNumber
private Animator prepareAnimator() {
AnimatorSet animation = new AnimatorSet(); // 进度条动画
ObjectAnimator progressAnimator = ObjectAnimator.ofFloat(mCdDrawable, "progress", 1f, 0f);
progressAnimator.setDuration(5000);
progressAnimator.setInterpolator(new LinearInterpolator());
progressAnimator.addListener(new Animator.AnimatorListener() { @Override
public void onAnimationStart(Animator animation) { } @Override
public void onAnimationRepeat(Animator animation) { } @Override
public void onAnimationEnd(Animator animation) {
mIv.setVisibility(View.GONE);
} @Override
public void onAnimationCancel(Animator animation) {
mIv.setVisibility(View.GONE);
}
}); // 居中的倒计时数字
ObjectAnimator showNumberAnimator = ObjectAnimator.ofInt(mCdDrawable, "showNumber", 5, 0);
showNumberAnimator.setDuration(5000);
showNumberAnimator.setInterpolator(new LinearInterpolator()); animation.playTogether(progressAnimator, showNumberAnimator);
return animation;
}
最后在button中添加点击事件
private View.OnClickListener mBtnOnClickListener = new View.OnClickListener() { @Override
public void onClick(View v) {
if(mAnimator != null) {
mAnimator.cancel();
}
mIv.setVisibility(View.VISIBLE);
mAnimator = prepareAnimator();
mAnimator.start();
}
};