• 一起Talk Android吧(第四百一十八回:制作时钟)


    各位看官们大家好,上一回中咱们说的例子是"解决Glide不能加载网络图片的方法",这一回咱们介绍的例子是"制作时钟"。闲话休提,言归正转,让我们一起Talk Android吧!

    看官们,我们在前面章回中介绍了绘图相关的内容,本章回中将对这些知识做一个综合应用,以加深大家对绘图知识的理解。综合应用的例子是一个时钟,我们将介绍如何使用绘图知识来制作一个时钟。时钟的最终效果如下图所示:
    在这里插入图片描述

    整体思路

    使用一块画布来绘制时钟,时钟是一个整体,不可能一次性全部把它全部绘制出来,因此把时钟拆分成小的模块,分模块来绘制。时钟可以拆分成表盘,表盘上的刻度和数字,指示时间的三个指针。我们将按分别绘制这些模块,最后将模块组成一个完整的时钟。

    准备画布

    我们自定义一个View并且重写View中的onDraw()方法,该方法的参数就是画布,我们将使用此画布来绘制时钟。

    绘制表盘

    时钟的表盘是圆形,我们在画布上画一个圆来表示表盘,画圆使用drawCircle()方法,圆心为画布的中心,半径使用自定义的数值,不过此值要小于画布的宽度,不然画布上无法显示完整的圆。

    绘制刻度

    时钟有60个刻度,而且刻度上还有数字。刻度就是一条直线,只是直线的长度和粗细需要自定义,这个通过设置画笔的属性就可以实现。

    画直线使用drawLine()方法,起点是表盘,终点通过刻度的长度计算出来。刻度中有部分刻度为整小时,比如1,12等,这些刻度需要显示成数字,数字本质上是文字,使用drawText()方法就可以实现,不过要注意文字的长度和宽度会占用一部分空间。

    刻度的起点位于表盘上,而且坐标都不同。我们使用旋转画布的思路,以表盘12点方向为刻度起点,每画一个刻度把画布旋转一个角度,角度值为60(360/60)这样保证了刻度的起点不变,变的是画布的角度。这个思路比较抽象,如果有看官不理解的话可以自己动手在纸上画画。按照此思路
    来个循环,把60个刻度全部画出来,在画的过程中计算每个整点刻度,将整点刻度画成粗线或者数字。

    绘制指针

    指针一共三个,分别指示小时,分钟和秒。绘制指针的思路和绘制刻度的思路相同:旋转布画。不同点在于指针的起点是圆心,也就是时钟表盘的中央。每个指针的长度不同,这点通过计算得出,主要体现在终点的坐标上。每个指针的粗细也不同,通过配置画笔的属性来实现。

    示例代码

    下面是完成的示例代码,代码中添加了详细的注释,请大家参考:

       private void initPaint() {
            mHousePaint = new Paint();
            //设置画笔颜色
            mHousePaint.setColor(Color.BLUE);
            //设置画笔为属性为STROKE,表示普通画笔,和正常笔写字画画一样,
            //还有一种属性为FILL,它是默认属性值,表示填充。类似刷子,画的范围比较大。
            mHousePaint.setStyle(Paint.Style.STROKE);
            //设置画笔的宽度,类似铅笔的粗和细
            mHousePaint.setStrokeWidth(3);
            //设置是否抗锯齿
            mHousePaint.setAntiAlias(true);
    
            //画刻度的画笔
            mTextPaint = new Paint();
            mTextPaint.setColor(Color.GRAY);
            mTextPaint.setTextSize(30);
            mTextPaint.setStyle(Paint.Style.FILL);
    
            //画整点数字的刻度或者粗线的画笔
            mTextBPaint = new Paint();
            mTextBPaint.setColor(Color.BLACK);
            mTextBPaint.setTextSize(30);
            mTextBPaint.setStrokeWidth(6);
    
            //画小时指针的画笔
            mHourPaint = new Paint();
            mHourPaint.setColor(Color.BLACK);
            mHourPaint.setStrokeWidth(12);
    
            //画分钟指针的画笔
            mMinutePaint = new Paint();
            mMinutePaint.setColor(Color.BLACK);
            mMinutePaint.setStrokeWidth(8);
    
            //画秒针指针的画笔
            mSecondPaint = new Paint();
            mSecondPaint.setColor(Color.RED);
            mSecondPaint.setStrokeWidth(4);
    
            //画表盘的画笔
            mArcPaint = new Paint();
            mArcPaint.setAntiAlias(true);
            mArcPaint.setColor(Color.WHITE);
            mArcPaint.setStrokeWidth(2);
            mArcPaint.setStyle(Paint.Style.STROKE);
        }
    
        private void drawClockView(Canvas canvas) {
            //中心坐标,以View中心为表盘中心
            float oX = getWidth()/2;
            float oY = getHeight()/2;
            //刻度盘半径
            float r = 260;
            //刻度线的长度
            float scaleLen = 30;
            //刻度线之间的角度,一共60个刻度线,铺满一周为360度
            int angle = 360/60;
    
            //1.画表盘
            canvas.drawCircle(oX,oY,r,mArcPaint);
    
            canvas.save();
            //2.画刻度线
            //一共12个小时,每小时之间有5个空格,一共12*5个刻度线
            //从12点钟方向开始画刻度线,然后旋转画布,重复此过程直到最后一个刻度线
            //对于整点的刻度线加粗并且加长显示,或者显示为具体的数字,代码中用j表示
            for(int i=0,j=0; i<60; i++) {
                canvas.rotate(angle,oX,oY);
                if(i%5 == 0) {
                    //从12点钟方向开始画,因此起点为(oX,oY-r+2)+2是圆的宽度,这样画出的刻度在圆内
    //                canvas.drawLine(oX, oY - r+2, oX, oY - r + scaleLen+16, mTextBPaint);
                    if( 0 == j){
                        //从12点钟方向开始画,因此起点为(oX,oY-r),-8和+24是数字的长宽,这样画出的刻度在圆内,可以自动计算数字的长宽
                        canvas.drawText(String.valueOf(12+j++), oX-8, oY - r + 24, mTextBPaint);
                    }else {
                        canvas.drawText(String.valueOf(j++), oX-8, oY - r + 24, mTextBPaint);
                    }
                }else {
                    canvas.drawLine(oX,oY-r+2,oX,oY-r+scaleLen,mTextPaint);
                }
            }
            canvas.restore();
    
            //3.画小时、分钟、秒三个指针
            //获取当前的时间:小时、分钟、秒
            LocalDateTime nowTime = LocalDateTime.now();
            int hour = nowTime.getHour();
            int minute = nowTime.getMinute();
            int second = nowTime.getSecond();
    
            //画小时指针,每小时包含5个刻度,所以*5
            canvas.save();
            canvas.rotate(5*angle*(hour%12),oX,oY);
            canvas.drawLine(oX,oY,oX,oY-r/3,mHourPaint);
            canvas.restore();
    
            //画分钟指针
            canvas.save();
            canvas.rotate(angle*minute,oX,oY);
            canvas.drawLine(oX,oY,oX,oY-r*2/3,mMinutePaint);
            canvas.restore();
    
            //画秒指针
            canvas.save();
            canvas.rotate(angle*second,oX,oY);
            canvas.drawLine(oX,oY,oX,oY-r*5/6,mSecondPaint);
            canvas.restore();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108

    运行上面的代码就可以得到我们在开篇中演示的时钟。

    看官们,关于Android中"绘图时钟"的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!

  • 相关阅读:
    芯片工艺PVT STA分析 OCV分析
    java get post请求
    降噪耳机哪款比较舒适?比较舒适的降噪耳机盘点
    苹果ios应用ipa文件签名为什么需要签名才能上架?有没有别的方式替代苹果签名?
    flink StandAlone 单机部署
    Dubbo: 基于SpringBoot+Dubbo的Provider/Consumer的实践
    2022.7.1 Linux——网络
    自古以来,代理程序都是兵家折戟之地
    hitcontraining_uaf
    The Sandbox Alpha 第三季排行榜公布
  • 原文地址:https://blog.csdn.net/talk_8/article/details/127932159