自定义CountdownView实现倒计时功能

使用自定义View实现倒计时功能

当手机应用在安装后进行资源加载初始化的时候,为提高用户的使用体验,通常会以倒计时的形式给予用户一定的提示。

倒计时控件实现的功能

  • 显示时间进度
  • 显示倒计时

实现效果如图所示


这里写图片描述

在本篇博客中的代码会有部分缺省,源码链接

对自定义View的尺寸进行测量并绘制中间的大圆

View在绘制的过程中对于尺寸的测量主要在OnMeasure中进行,绘制中间的大圆需要指定圆心、半径、画笔样式、背景样式等信息。倒计时功能控件显示的为圆,因此以View中的长和宽的最小值作为直径。

绘制中间大圆的半径是通过getMeasuredWidth()/2来获取,在定义画笔时需要设置防锯齿

public class CountDownView extends android.support.v7.widget.AppCompatTextView {

    private int circleRadius;

    private int circleColor=0xff33b5e5;

    private Paint circlePaint;
    private Rect bounds;

    private int centerX;
    private int centerY;

    public CountDownView(Context context) {
        super(context);
        init();
    }

    public void init(){
        circlePaint=new Paint();
        bounds=new Rect();

    }

    public CountDownView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CountDownView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);

        circleRadius=getMeasuredWidth()>getMeasuredHeight()?getMeasuredHeight()/2:getMeasuredWidth()/2;
        setMeasuredDimension(getMeasuredWidth(),getMeasuredHeight());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        getDrawingRect(bounds);      //获取控件的边界

        centerX=bounds.centerX();
        centerY=bounds.centerY();

        //绘制中间的大圆的背景
        circlePaint.setAntiAlias(true);
        circlePaint.setStyle(Paint.Style.FILL);
        circlePaint.setColor(circleColor);
        canvas.drawCircle(bounds.centerX(),bounds.centerY(),circleRadius,circlePaint);

    }
}

在activity_main.xml中添加自定义控件,添加自定义控件时需要指定包名以及类型,CountDownView继承自TextView,所以其具有TextView的所有的属性。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    tools:context=".MainActivity">

    <com.example.wyw.countdowndemo.CountDownView
        android:layout_width="100dp"
        android:layout_height="100dp"
        />

</LinearLayout>

运行结果

这里写图片描述

绘制进度边框

进度边框的绘制需要在上面绘制大圆的基础上,进行绘制,绘制的是空心圆。

    private int cirlceBoundColor=0xff00ddff;

    @Override
    protected void onDraw(Canvas canvas) {

        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setStrokeWidth(5);
        circlePaint.setColor(cirlceBoundColor);
        canvas.drawCircle(bounds.centerX(),bounds.centerY(),circleRadius-8,circlePaint);

    }

运行结果

这里写图片描述

绘制进度条的一条弧线

进度条的绘制过程弧线不断增加绘制角度,然后更新视图显示的,先绘制一条角度为45度的弧线。进度条弧线绘制的边界与进度边框的边界相同,月进度边界的宽度也相同。

    private RectF arcRectF;
    private int processColor=0xff99cc00;

    public void init(){
        arcRectF=new RectF();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        circlePaint.setColor(processColor);
        //设置线冒样式
        circlePaint.setStrokeCap(Paint.Cap.ROUND);
        arcRectF.set(bounds.left+8,bounds.top+8,bounds.right-8,bounds.bottom-8);
        canvas.drawArc(arcRectF,-90,40,false,circlePaint);

    }

运行结果

这里写图片描述

进度条按照通过Timer不断控制绘制角度的增加

绘制角度=每一次需要绘制的角度*(已经绘制次数+1);当绘制结束后需要将timer取消。


    private int currentDrawTime;    //已经绘制的次数
    private Timer timer;

    public void init(){
        timer=new Timer();
        arcRectF=new RectF();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        arcRectF.set(bounds.left+8,bounds.top+8,bounds.right-8,bounds.bottom-8);
        canvas.drawArc(arcRectF,-90,currentDrawTime*45,false,circlePaint);

    }

    public void drawProcess(){

        currentDrawTime=0;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
               postInvalidate();
               currentDrawTime++;
               if (currentDrawTime==8)
                   timer.cancel();
            }
        },500,500);

    }

运行结果

这里写图片描述

倒计时时间绘制,倒计时的绘制,需要根据timer来进行倒计时


    @Override
    protected void onDraw(Canvas canvas) {
     Paint paint = getPaint();
        float textY = centerY - (circlePaint.descent() + circlePaint.ascent()) / 2;
        paint.setAntiAlias(true);  //防锯齿
        paint.setColor(Color.WHITE);
        paint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText((4000-500*currentDrawTime)/500+"s",centerY,textY,paint);

    }


这里写图片描述

源码地址

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值