仿华为天气刻度圆盘
来源:互联网 发布:妙趣横生的算法 pdf 编辑:程序博客网 时间:2024/04/29 20:08
————作为一个自学Android不久的渣渣,一直在各大博客网站看大神前辈们的技术文章,真的学到很多。最近自己防了华为天气的刻度圆盘UI,特意写了这篇文章,算是记录吧。
首先,本文参考http://m.blog.csdn.net/article/details?id=51111125的绘制,但是加入了更多的逻辑判断, 这里感谢作者。
先来看看最终效果:
可以看出这个UI就是一个自定义的View,由 刻度盘(白色线条、渐变色线条)、中间温度文字、周边温度文字等部分组成。我们先来看刻度盘的绘制。
刻度盘的绘制
绘制这个刻度盘其实很简单,我们有几种方式可以绘制出来,一是旋转画布来达到效果,但是由于后面绘制周边最低温度和最高温度文字显示时,需要一个确切的坐标才能正确显示文字的位置,所以这里不考虑使用。二就是确定一个圆心,以及半径,然后遍历整个圆的度数,计算出每增加某个角度后顶点的X、Y坐标,然后依次绘制出线条。
由于需要根据角度计算坐标长度,因此需要用到一点勾股定理,所以先确定两个方法:
/** * 根据半径和角度计算x坐标 */private float calculateX(float r, double angle) { angle = angle * ((2 * Math.PI) / 360); double x = r * Math.sin(angle); double xFinal = centerX + x; return (float) xFinal;}/** * 根据半径和角度计算y坐标 */private float calculateY(float r, double angle) { angle = angle * ((2 * Math.PI) / 360); double y = r * Math.cos(angle); double yFinal = centerY - y; return (float) yFinal;}
先把角度换算成弧度,然后根据弧度计算X 、Y坐标。
现在遍历角度,我们把整个圆分为120份,每条线间隔3°,根据半径和此时的角度计算出坐标,线条的长度为l,
@Overrideprotected void onDraw(Canvas canvas) { canvas.save(); for (double angle = 0; angle <= 360d; angle += 3.0d) { float xStart = calculateX(r, angle); float xStop = calculateX(r - l, angle); float yStart = calculateY(r, angle); float yStop = calculateY(r - l, angle); //绘制起始角度和终止角度的着色线条 //根据起始角度和终止角度所在位置,大致可以分为三种情况 if (((startAngle>=0&&startAngle<180) && (stopAngle>=0&&stopAngle<180)) || ((startAngle>180&&startAngle<360) && (stopAngle>180&&stopAngle<360))){ //当起始角度和终止角度都在左边半圆 或者都在右边半圆时 if (angle <= stopAngle && angle >= startAngle) { linePaint.setShader(mShader); } else linePaint.setShader(mWhiteShader); } else if ((startAngle>180&&startAngle<=360) && (stopAngle>=0&&stopAngle<180)) { //当起始角度在左边半圆 终止角度在右边半圆时 if ((angle>=0&&angle<=stopAngle) || (angle>=startAngle&&angle<=360)) { linePaint.setShader(mShader); } else { linePaint.setShader(mWhiteShader); } } //刻度盘大致为两种长度和宽度的线条 if (angle == 207 || angle == 153) { //绘制边界位置的两条线条 linePaint.setStrokeWidth(2); float xStartL = calculateX(r * 1.05f, angle); float xStopL = calculateX((r - l), angle); float yStartL = calculateY(r * 1.05f, angle); float yStopL = calculateY((r - l), angle); canvas.drawLine(xStartL, yStartL, xStopL, yStopL, linePaint); //底部两条较长的线 } else if (!(angle < 207 && angle > 153)) { //绘制其他位置的线条 linePaint.setStrokeWidth(3); canvas.drawLine(xStart, yStart, xStop, yStop, linePaint); // 画短线 } } //绘制最低温度、最高温度、中心实时温度 drawCenterTem(canvas); drawStartTem(canvas); drawStopTem(canvas); canvas.restore();}
由于在最低温度和最高温度中间的线条都要着色,因此加入判断。还有刻度盘边界的两条线段长度不同,也需加上判断,注释已经写的很详细了。另外记得在Draw()方法中,里面的绘制逻辑都应被包含在canvas.save()、canvas.restore()之间,避免当数据改变时,视图没有做出变动。
剩下的绘制温度文字部分已经很明朗了,
/** * 画中心位置温度 * * @param canvas */private void drawCenterTem(Canvas canvas) { mTextPaint.setTextSize(r * 0.6f); mTextPaint.setAntiAlias(true); mTextPaint.setTextAlign(Paint.Align.CENTER); float textY = centerY - (mTextPaint.descent() + mTextPaint.ascent()) / 2; canvas.drawText(centerTemper+"°", centerX, textY, mTextPaint);}/** * 画起始温度 */private void drawStartTem(Canvas canvas) { mTextPaint.setTextSize(r * 0.1f); canvas.drawText(startTem + "°", calculateX(r * 1.1f, startAngle), calculateY(r * 1.1f, startAngle), mTextPaint);}/** * 画截至温度 */private void drawStopTem(Canvas canvas) { mTextPaint.setTextSize(r * 0.1f); canvas.drawText(stopTem + "°", calculateX(r * 1.1f, stopAngle), calculateY(r * 1.1f, stopAngle), mTextPaint);}
另外在使用Draw()之前,我们在onWindowFocusChanged()方法中获取诸如手机屏幕的高和宽,继而计算出圆心、半径、线条长度等数据,以及使用Shader为画笔设置颜色渐变效果,代码如下:
@Overridepublic void onWindowFocusChanged(boolean hasWindowFocus) { int viewWidth = getWidth(); int viewHeight = getHeight(); centerX = viewWidth / 2f; centerY = viewHeight / 2f; r = viewWidth * 0.4f; l = viewWidth * 0.05f; //设置渐变色 mShader = new SweepGradient(centerX, centerY, new int[] { Color.parseColor("#FB8B13"), Color.parseColor("#FB1414"), Color.parseColor("#1488FB"), Color.parseColor("#13FBE0"), Color.parseColor("#8BFB13"), Color.parseColor("#FB8B13")}, null); mWhiteShader = new SweepGradient(centerX, centerY, new int[] { Color.WHITE, Color.WHITE }, null); linePaint.setShader(mShader); invalidate();}
这里我们使用的是梯度渲染来达到想要的效果,由于梯度渲染开始渲染的位置默认为90°,会导致颜色显示很突兀,因为我们第一个颜色和最后一个颜色设置成一样的,这样就首尾相连了。
最后,文章到此结束,其实绘制还是比较容易的,只是在最低温度和最高温度的显示上,根据温度,计算出起始和终止角度的逻辑上有点坑。我采用了比较傻的方法,如果有人有更好的方法,希望不惜赐教。
作者邮箱:13642948820@163.com
QQ号码:497078141
项目地址:https://github.com/yinyiliang/WindCloud
作者另一个项目:https://github.com/yinyiliang/YunGirl
最后,作者正在找工作,坐标广州,有没有哪位大大能介绍个工作呀!!/(ㄒoㄒ)/~~
- 仿华为天气刻度圆盘
- ##仿华为天气动画
- Android仿华为天气绘制刻度盘
- Android仿华为天气绘制刻度盘
- 仿遥控器菜单圆盘
- 实现一个仿华为天气的进度圆
- 百度桌面圆盘高仿
- 高仿百度桌面圆盘
- 百度桌面圆盘高仿
- Android圆盘刻度,类似体重测试仪,效果不错哦
- android自定义View之(六)------高仿华为荣耀3C的圆形刻度比例图(ShowPercentView)
- Android中仿IOS圆盘时间选择器
- 圆盘
- 圆盘
- 高仿墨迹天气黄历
- 仿墨迹天气折线图
- 仿天气日出日落效果
- Android 高仿【优酷】圆盘旋转菜单的实现
- 进程
- 二分图最大匹配问题与匈牙利算法的核心思想
- SDUT2413n a^o7 !
- Android Dialog的五种常见使用
- POJ3278 Catch That Cow(最短路+bfs)
- 仿华为天气刻度圆盘
- Java日志实战及解析 - 引导
- 四大组件BroadcastReceiver的工作过程
- mysql 5.7 版本解压版windows下的安装
- 含有中文的字符串截取类
- 初学线段树总结
- BestCoder Round #85题解
- Oracle序列
- Socket网络编程中的一些问题(Linux)