Android自定义View之[可以走动的时钟]

效果图如下:

绘制流程:

  • 绘制表盘
  • 绘制刻度
  • 绘制数字
  • 旋转数字
  • 绘制时分秒指针
  • 使用Handler定时刷新指针

接下来一步一步实现:

  • 绘制表盘

canvas.drawCircle(mWidth / 2, mHeight / 2, mHeight / 2 - dp2px(borderPadding), mPaint);
  • 绘制刻度

        //绘制刻度,每次绘制完需要旋转一定的角度,然后继续绘制
        for (int i = 0; i < 60; i++) {
            if (i % 5 == 0) { //大刻度
                mPaint.setStrokeWidth(dp2px(3));
                canvas.drawLine(mWidth / 2, dp2px(borderPadding), mWidth / 2, dp2px(23), mPaint);
            } else { //小刻度
                mPaint.setStrokeWidth(dp2px(1));
                canvas.drawLine(mWidth / 2, dp2px(borderPadding), mWidth / 2, dp2px(20), mPaint);
            }
            //一共绘制60个刻度,每次旋转360°/60
            canvas.rotate(360 / 60, mWidth / 2, mHeight / 2);
        }
  • 绘制数字

        //绘制刻度数字
        for (int i = 0; i < 12; i++) {
            //绘制数字,一共12个
            canvas.drawText(String.valueOf(i==0?"12":i), mWidth / 2, dp2px(textPadding), mPaint);
        }
  • 旋转数字

这里为什么要旋转数字呢?有人可能会注意到数字随着角度旋转了,这样很不友好,所以我们需要把数字都"正"过来
        //绘制刻度数字
        for (int i = 0; i < 12; i++) {
            //保存当前画布状态
            canvas.save();
            //将要旋转的中心点定位到数字上,旋转的角度取决于当前数字倾斜的角度
            canvas.rotate(-360/12*i, mWidth / 2, dp2px(textPadding)- mPaint.measureText(String.valueOf(i==0?"12":i)) / 2);
            //绘制数字
            canvas.drawText(String.valueOf(i==0?"12":i), mWidth / 2, dp2px(textPadding), mPaint);
            //恢复被旋转的画布
            canvas.restore();
            //绕表盘中心旋转,绘制下一个刻度
            canvas.rotate(360 / 12, mWidth / 2, mHeight / 2);
        }
图中可以看到,刻度上的数字已经都"正"过来了

  • 绘制时分秒指针

        //绘制秒针
        mPaint.setStrokeWidth(dp2px(1));
        mPaint.setColor(Color.BLACK);
        canvas.save();
        canvas.rotate(second * (365 / 60), mWidth / 2, mHeight / 2);
        canvas.drawLine(mWidth / 2, dp2px(textPadding) + dp2px(10), mWidth / 2, mHeight / 2 + dp2px(20), mPaint);
        canvas.restore();
        //绘制分针
        mPaint.setStrokeWidth(dp2px(3));
        mPaint.setColor(Color.BLACK);
        canvas.save();
        canvas.rotate((minute + (float) second / 60) * 360 / 60, mWidth / 2, mHeight / 2);
        canvas.drawLine(mWidth / 2, dp2px(textPadding) + dp2px(20), mWidth / 2, mHeight / 2 + dp2px(20), mPaint);
        canvas.restore();
        //绘制时针
        mPaint.setStrokeWidth(dp2px(5));
        mPaint.setColor(Color.BLACK);
        canvas.save();
        canvas.rotate((hour + (float) minute / 60) * 360 / 12, mWidth / 2, mHeight / 2);
        canvas.drawLine(mWidth / 2, dp2px(textPadding) + dp2px(50), mWidth / 2, mHeight / 2 + dp2px(20), mPaint);
        canvas.restore();
        //绘制中心圆点
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(mWidth / 2, mHeight / 2, dp2px(5), mPaint);
  • 使用Handler定时刷新指针

上面绘制时分秒指针的时候已经在代码逻辑中加入根据时间来绘制不同的角度,这里我们只需要每隔一秒重新获取一次系统时间,并调用invalidate()方法重新绘制界面,时钟就可以"动"起来了
    private Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                mCalendar = Calendar.getInstance();
                //重新绘制页面
                invalidate();
                //1000ms后再刷新一次页面
                sendEmptyMessageDelayed(0, 1000);
            }
        };
        //获取当前时间
        int second = mCalendar.get(Calendar.SECOND);
        int hour = mCalendar.get(Calendar.HOUR);
        int minute = mCalendar.get(Calendar.MINUTE);
        ...
        //绘制时分秒指针
        ...
  • 扫码体验Demo

  • 欢迎star

源码已上传到Github: https://github.com/lvkaixuan/ClockView

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值