自定义view(二)之钟表

有时间学习还要有时间总结,感觉学习真是痛苦,痛不欲生、痛苦并快乐着,学会了如果不记下来那么最后的结果就是忘记了,啥也不记得了,以后忘了也没有个地方去查,所以现在我就要做这个工作。其实做表这个demo是17年的8月31号,本来我其实就想画了表盘呢(也是没啥志气),没想到花完感觉空落落的,光秃秃的也不好看,我就想找找看看大家大家的思路是啥,怎么能让那个秒针动弹,然后还真有很简单的方法 postInvalidateDelayed(1000)(我试过这个方法,写1也是1秒,还不知道原理)。如果解决了这个问题那么做一个钟表很简单的,大概思路是这样的:
1.先把画笔的中点移到屏幕中心,画圆,外边画一个方,然后白色的背景就是表盘了,画刻度
2.计算秒针、分针、时针的角度,这就完成了。

先上一个图吧

表的图

思路讲完了,现在就是coding了,顺便也说一下一些方法的用法

这就是第一步,把基本的表盘给花出来
private void drawCircle(Canvas canvas) {
    r = (float) (Math.min(mWidth, mHeight)/2 *0.8);
    canvas.translate(mWidth/2, mHeight /2);//移动画布中心点到屏幕中央
    paint.setColor(getResources().getColor(R.color.brown));//设置画笔的颜色
    canvas.drawRect(-r-20,-r-20,r+20,r+20,paint);//画一个正方形,就是外边褐色的框
    paint.setColor(getResources().getColor(R.color.black));
    paint.setStyle(Paint.Style.FILL);//设置画笔是实心的,画出表盘的圆来
    paint.setColor(getResources().getColor(R.color.white));
    canvas.drawCircle(0,0,r+5,paint);

    paint.setStyle(Paint.Style.STROKE);//设置画笔为描边
    paint.setColor(getResources().getColor(R.color.black));
    paint.setStrokeWidth(1);
    paint.setTextSize(15);
    canvas.save();//保存画布

    int lineWidth;
    for (int i = 0; i < 60; i++) {//现在就是要画出表盘的那些个刻度
        if (i % 5 == 0) {//是画整点的刻度的,比如12,1,2,3点
            paint.setStrokeWidth(3);//设置一下画笔的宽度
            lineWidth = 20;//设置整点刻度的线长度
            String text = String.valueOf(12 - i/5);//计算当前要填写的数字
            Rect textBound = new Rect();
            paint.getTextBounds(text, 0, text.length(), textBound);
            canvas.save();
            paint.setStrokeWidth(2);
            paint.setTextSize(25);
            paint.setStyle(Paint.Style.FILL);
            canvas.translate(0,10+lineWidth-r+(textBound.bottom - textBound.top));
            canvas.rotate(6 * i);//做一下画布的旋转,这样数字的显示就是正常的哩
            canvas.drawText(text, -(textBound.right - textBound.left) / 2,10, paint);
            canvas.restore();
        }else{//画每一分的小刻度的
            paint.setStrokeWidth(1);
            lineWidth = 10;
            paint.setStrokeWidth(1);
        }
        canvas.drawLine(0,-r+10,0,10+lineWidth-r,paint);
        canvas.rotate(-360/60);//画布逆时针赚
    }
    canvas.restore();
}
表盘的图

表盘花完了就是做最重要的一步了,就是让表动起来,怎么让表动,就是定时的刷新,怎么做定时刷新,其实定时刷新还挺多的用Timer+handler等等一些,现在我就用一个简单的postInvalidateDelayed()方法。

/**
 * 表的指针
 * @param canvas 第一版使用的是60分的,每一秒6度
 */
private void drawPointer(Canvas canvas){
    Calendar calendar = Calendar.getInstance();
    int hour = calendar.get(Calendar.HOUR_OF_DAY); //时
    int minute = calendar.get(Calendar.MINUTE); //分
    int second = calendar.get(Calendar.SECOND); //秒
    int angleHour = ((hour % 60) * 360 / 12); //时针转过的角度
    int angleMinute = minute * 360 / 60; //分针转过的角度
    int angleSecond = second * 360 / 60; //秒针转过的角度
    paint.setStyle(Paint.Style.FILL);


    canvas.save();//分针转动
    paint.setColor(getResources().getColor(R.color.black));
    canvas.rotate(angleMinute);//旋转画布 angleMinute的角度
    RectF rectFMinute = new RectF(-4, -r*2/3,  4, 30);
    canvas.drawRoundRect(rectFMinute, 10, 10, paint);
    canvas.restore();

    int hourMinute = angleMinute / (6 * 12);//时针转动
    if (hourMinute > 0) {//主要实现让时针12分钟转动一格,
        // 防止时针一小时转一大格不好看
        canvas.save();
        canvas.rotate(angleHour+hourMinute * 6);
        RectF rectFHour1 = new RectF(-6, -r/2,  6, 30);
        canvas.drawRoundRect(rectFHour1, 10, 10, paint);
        canvas.restore();
    }else{
        canvas.save();
        canvas.rotate(angleHour);
        RectF rectFHour = new RectF(-6, -r/2,  6, 30);
        canvas.drawRoundRect(rectFHour, 10, 10, paint);
        canvas.restore();
    }

    canvas.save();//秒针转动
    paint.setColor(getResources().getColor(R.color.red));
    canvas.drawCircle(0,0,15,paint);
    canvas.rotate(angleSecond);
    RectF rectFSecond = new RectF(-3, -r+5,  3, 30);
    canvas.drawRoundRect(rectFSecond, 10, 10, paint);
    canvas.restore();
}

这个是我刚开始的写法,如果这么写就会有一个不好看的地方就是分针每次一小格,感觉太明显了,当然这个问题不是我发现的,是我女朋友说的:那个分针怎么那么转呀,一下跳那么大老远。没办法,女朋友都容忍不了说明是大问题,我就想要不和分针一样,然后就把一小格继续细分让分针实现成一分钟慢慢的调一格也就是6度,12秒钟调一度,5个12秒刚好事一格。

/**
 * 表的指针
 * @param canvas 第二版使用的是每一分下边再细分6度,这样就可以让指针变化的范围更小
 */
private void drawPointerSecond(Canvas canvas){
    Calendar calendar = Calendar.getInstance();
    int hour = calendar.get(Calendar.HOUR_OF_DAY); //时
    int minute = calendar.get(Calendar.MINUTE); //分
    int second = calendar.get(Calendar.SECOND); //秒
    int angleHour = ((hour % 60) * 360 / 12); //时针转过的角度
    int angleMinute = minute * 360 / 60; //分针转过的角度
    int angleSecond = second * 360 / 60; //秒针转过的角度
    paint.setStyle(Paint.Style.FILL);


    int minuteSecond = angleSecond/(6*10);
    if (minuteSecond>0) {

        canvas.save();//分针转动
        paint.setColor(getResources().getColor(R.color.black));
        canvas.rotate(angleMinute + minuteSecond);//旋转画布 angleMinute的角度
        RectF rectFMinute = new RectF(-4, -r*2/3,  4, 30);
        canvas.drawRoundRect(rectFMinute, 10, 10, paint);
        canvas.restore();

    }else{

        canvas.save();//分针转动
        paint.setColor(getResources().getColor(R.color.black));
        canvas.rotate(angleMinute);//旋转画布 angleMinute的角度
        RectF rectFMinute = new RectF(-4, -r*2/3,  4, 30);
        canvas.drawRoundRect(rectFMinute, 10, 10, paint);
        canvas.restore();

    }

    
    int hourMinute = angleMinute / (6 * 12);//时针转动
    if (hourMinute > 0) {//主要实现让时针12分钟转动一格,
        // 防止时针一小时转一大格不好看
        canvas.save();
        canvas.rotate(angleHour+hourMinute * 6);
        RectF rectFHour1 = new RectF(-6, -r/2,  6, 30);
        canvas.drawRoundRect(rectFHour1, 10, 10, paint);
        canvas.restore();
    }else{
        canvas.save();
        canvas.rotate(angleHour);
        RectF rectFHour = new RectF(-6, -r/2,  6, 30);
        canvas.drawRoundRect(rectFHour, 10, 10, paint);
        canvas.restore();
    }


    canvas.save();//秒针转动
    paint.setColor(getResources().getColor(R.color.red));
    canvas.drawCircle(0,0,15,paint);
    canvas.rotate(angleSecond);
    RectF rectFSecond = new RectF(-3, -r+5,  3, 30);
    canvas.drawRoundRect(rectFSecond, 10, 10, paint);
    canvas.restore();
}

表就做完了,只要引用到布局文件里就可以了。 这是我的git博客,这里是我的git地址欢迎大家star和fork

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容