简单的自定义View——表盘时钟
来源:互联网 发布:我国能源现状数据 编辑:程序博客网 时间:2024/04/30 17:38
简单的自定义View——表盘时钟
先看看效果
先缕一下思路,看下绘制过程
- 先绘制外面的大圆
- 再绘制圆心
- 接着绘制时钟刻度
- 然后绘制秒指针
- 绘制分指针
- 绘制时指针
- 绘制好后初始化时间,获取时,分,秒
- 接着用postInvalidateDelayed(1000)方法来定时1秒刷新View
关键点在于使用旋转画布,以及计算圆周长上各点坐标
选择画布canvas.rotate(angle, x, y); // (x,y)旋转点 angle选择角度
圆上点a,b计算公式:
a = r * sin(angle) + x
b = y - r * cos(angle)
绘制过程onDraw方法如下
- initClock()
- drawBigCircle(canvas)
- drawkedu(canvas)
- drawNumber(canvas)
- drawHour(canvas, hourAngle)
- drawMinute(canvas, minuteAngle)
- drawSecond(canvas, secondAngle)
- drawSmallCircle(canvas)
- postInvalidateDelayed(1000)
接着就是实现各种绘制方法了
// 外面的大圆 private void drawBigCircle(Canvas canvas) { mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(Dp2Px(getContext(),1)); canvas.drawCircle(x, y, r, mPaint); } // 圆心 private void drawSmallCircle(Canvas canvas) { mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.FILL); canvas.drawCircle(x, y, Dp2Px(getContext(),5), mPaint); } // 刻度 private void drawkedu(Canvas canvas) { for (int i = 0; i < 60; i++) { // 如果i除于5余数为0即比较粗的时刻线 if (i % 5 == 0) { mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(Dp2Px(getContext(),3)); canvas.drawLine(x, y - r, x, y - r + Dp2Px(getContext(),14), mPaint); } else { mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(Dp2Px(getContext(),2)); canvas.drawLine(x, y - r, x, y - r + Dp2Px(getContext(),9), mPaint); } canvas.rotate(6, x, y); } } // 刻度上的时间数字 private void drawNumber(Canvas canvas) { mPaint.setColor(Color.BLACK); mPaint.setTextSize(Dp2Px(getContext(),14)); mPaint.setTextAlign(Paint.Align.CENTER); // 设置文本水平居中 float fontHeight = (mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top); // 获取文字高度用于设置文本垂直居中 // 数字离圆心的距离 float distance = r - Dp2Px(getContext(),25); // 数字的坐标(a,b) float a, b; // 每30度写一个数字 for (int i = 0; i < 12; i++) { a = (float) (distance * Math.sin(i * 30 * (Math.PI / 180)) + x); b = (float) (y - distance * Math.cos(i * 30 * (Math.PI / 180))); if (i == 0) { // 本以为font_height/2即可获得文字一半的高度,实测除以3.5才是,不明觉厉 canvas.drawText("12", a, (float) (b + fontHeight / 3.5), mPaint); } else { canvas.drawText(String.valueOf(i), a, (float) (b + fontHeight / 3.5), mPaint); } } } // 秒指针 private void drawSecond(Canvas canvas, float second) { mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(Dp2Px(getContext(),2)); // 指针的长度 float pointLenth = r - Dp2Px(getContext(),15); // 指针末尾的坐标(a,b) float a = (float) (pointLenth * Math.sin(second * (Math.PI / 180)) + x); float b = (float) (y - pointLenth * Math.cos(second * (Math.PI / 180))); canvas.drawLine(x, y, a, b, mPaint); } // 分钟指针 private void drawMinute(Canvas canvas, float minute) { mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(Dp2Px(getContext(),3)); // 指针的长度 float pointLenth = r - Dp2Px(getContext(),35); // 指针末尾的坐标(a,b) float a = (float) (pointLenth * Math.sin(minute * (Math.PI / 180)) + x); float b = (float) (y - pointLenth * Math.cos(minute * (Math.PI / 180))); canvas.drawLine(x, y, a, b, mPaint); } // 小时指针 private void drawHour(Canvas canvas, float hour) { mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(Dp2Px(getContext(),4)); // 指针的长度 float pointLenth = r - Dp2Px(getContext(),50); // 指针末尾的坐标(a,b) float a = (float) (pointLenth * Math.sin(hour * (Math.PI / 180)) + x); float b = (float) (y - pointLenth * Math.cos(hour * (Math.PI / 180))); canvas.drawLine(x, y, a, b, mPaint); }
初始化时间
// 获取时间 private void initClock() { SimpleDateFormat format = new SimpleDateFormat("HH-mm-ss"); String time = format.format(new Date(System.currentTimeMillis())); String[] split = time.split("-"); float hour = Integer.parseInt(split[0]); float minute = Integer.parseInt(split[1]); float second = Integer.parseInt(split[2]); //秒针走过的角度 secondAngle = second * 6; //分针走过的角度 minuteAngle = minute * 6 + second / 10; //时针走过的角度 hourAngle = hour * 30 + minute / 10; }
Dp像素转化
/** * 屏幕DP转PX **/ public int Dp2Px(Context context, float dp) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); } /** * 屏幕PX转DP **/ public int Px2Dp(Context context, float px) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (px / scale + 0.5f); }
完整源码下载地址https://github.com/LiLinXiang/ClockView
0 0
- 简单的自定义View——表盘时钟
- 自定义时钟View,表盘的绘制
- 自定义View基础篇——表盘
- Android 自定义View——表盘实例
- 自定义View 手表表盘
- 自定义View-汽车表盘
- android一个简单的自定义表盘
- Android自定义View----时钟/仪表盘的简单实现
- android 自定义view实现表盘效果
- Android 自定义View 实现表盘效果
- Android 自定义view(画表盘)
- Android 自定义View 实现表盘效果
- android 自定义 view 实现表盘效果
- iOS——简单的自定义view
- 自定义组件的简单使用—View
- Js版带表盘的时钟
- Android 绘图基础:Canvas画布——自定义View基础(绘制表盘、矩形、圆形、弧、渐变)
- Android 绘图基础:Canvas画布——自定义View基础(绘制表盘、矩形、圆形、弧、渐变)
- [LeetCode]--61. Rotate List
- android 中 tableLayout
- linear convolution/periodic convolution/circular convolution
- Dlib 19.2+VS2015 人脸检测(非CMake)
- android 开发资源
- 简单的自定义View——表盘时钟
- dubbo 使用学习七(结果缓存)
- LeetCode 446. Arithmetic Slices II - Subsequence
- 9、(知识篇)JAVA反射(1)
- String,StingBuffer,StingBuilder
- [Python]DJango部署在Apache服务器配置示例
- 【快速幂模板】 nyoj102 次方求摸 420 p次方求和(快速幂+同余定理)
- 10、(知识篇)JAVA反射(2)
- 排序之归并排序