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     @Override
23     public void draw(Canvas canvas) {
24         // TODO Auto-generated method stub
25
26     }
27
28     @Override
29     public void setAlpha(int alpha) {
30         mPaint.setAlpha(alpha);
31     }
32
33     @Override
34     public void setColorFilter(ColorFilter cf) {
35     }
36
37     @Override
38     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         @Override
11         public void onAnimationStart(Animator animation) {
12
13         }
14
15         @Override
16         public void onAnimationRepeat(Animator animation) {
17
18         }
19
20         @Override
21         public void onAnimationEnd(Animator animation) {
22             mIv.setVisibility(View.GONE);
23         }
24
25         @Override
26         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

时间: 2024-11-06 03:29:33

Android自定义View之倒计时Countdown实现的相关文章

Android 自定义View合集

自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/Mr-XiaoLiang 自定义控件三部曲 http://blog.csdn.net/harvic880925?viewmode=contents Android 从0开始自定义控件之View基础知识与概念 http://blog.csdn.net/airsaid/article/details/5

Android自定义View探索(一)—生命周期

Activity代码: public class FiveActivity extends AppCompatActivity { private MyView myView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e("log", "Activity生命周期:onCreate"); setConte

Android 自定义View视图

创建全新的视图将满足我们独特的UI需求. 本文介绍在指南针开发中会用到的罗盘的界面UI,通过继承View类实现的自定义视图,以此来深刻了解自定义视图. 实现效果图: 源代码: 布局文件activity_main(其中CompassView继承View类): <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.

android自定义View (一)MeasureSpec

A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement for either the width or the height. A MeasureSpec is comprised of a size and a mode. There are three possible modes: UNSPECIFIED

(转)[原] Android 自定义View 密码框 例子

遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 样子 支持的样式 可以通过XML定义影响外边和行为的属性如下 边框圆角值,边框颜色,分割线颜色,边框宽度,密码长度,密码大小,密码颜色 <declare-styleable name="PasswordInputView"> <attr name="border

Android自定义View——圆形进度条式按钮

介绍 今天上班的时候有个哥们问我怎么去实现一个按钮式的进度条,先来看看他需要实现的效果图. 和普通的圆形进度条类似,只是中间的地方有两个状态表示,未开始,暂停状态.而且他说圆形进度的功能已经实现了.那么我们只需要对中间的两个状态做处理就行了. 先来看看实现的效果图: 上面说了我们只需要处理中间状态的变化就可以了,对于进度的处理直接使用了弘洋文章中实现: http://blog.csdn.net/lmj623565791/article/details/43371299 下面开始具体实现. 具体实

android 自定义View【2】对话框取色&amp;色盘取色的实现

android 自定义View[2]对话框取色&色盘取色的实现    上一篇文章基本介绍了android自定义view的流程:继承view,复写view的一些方法.实现简单的自定义view.这篇文章主要介绍的是系统对话框取色功能,然后顺便介绍升级版,色盘取色[类似于ps中的吸管,对图片点击相应位置,获取那个位置的颜色]. 一.概述:通过该例子了解以下内容: 1.进一步了解android 自定义view. 2.知道如何获取图片上的颜色值. 3.监听屏幕touch,实现移动的时候自动取色.[onDr

Android自定义View(二、深入解析自定义属性)

转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51468648 本文出自:[openXu的博客] 目录: 为什么要自定义属性 怎样自定义属性 属性值的类型format 类中获取属性值 Attributeset和TypedArray以及declare-styleable ??在上一篇博客<Android自定义View(一.初体验)>中我们体验了自定义控件的基本流程: 继承View,覆盖构造方法 自定义属性 重写onMeasure方法测量宽

Android 自定义 view(三)&mdash;&mdash; onDraw

前言: 上一篇已经介绍了用自己定义的属性怎么简单定义一个view<Android 自定义view(二) -- attr 使用>,那么接下来我们继续深究自定义view,下一步将要去简单理解自定义view的两个比较重要的方法 onDraw(Canvas canvas) ,在探究 onDraw方法之前,我们必须先深入了解两个类Paint和Canvas .   第一:认识Paint 在探究onDraw之前首先必须要认识两个类,这里给出非常不错的两个资料参考网站,我也是从这里得到想要知道的东西,简单的说