| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android jetpack compose 绘制折线图 -> 正文阅读 |
|
[移动开发]Android jetpack compose 绘制折线图 |
(又是自造轮子的一天) 先看效果图: ?需要用到的知识点: jetpack compose 绘图部分的api; 少部分高中数学知识。 一、折线图载体这里折线图的载体,使用的是Card,嵌套一个Canvas,而Canvas正是图形接口的载体:
解释一下上面的代码,这里的折线图是根据我们的业务需求来实现的,其中: times:横轴上的每个坐标显示的文本,因为我们的业务需求是绘制某变量随时间变化的曲线,所以这里使用的是times作为横轴的变量名。 color:每条曲线的颜色。原则上这个颜色列表的长度应该跟后面的数据数组的长度是一致的,但是在绘制曲线的时候,这里只会根据数据数组的索引在颜色列表中取值,所以颜色列表的长度应当大于或等于数据数组的长度。 data:数据数组,数组中的每条数据对应于折线图上的一条曲线。 chartTitle:折线图上的标题。 当然,一个折线图可定制的内容还有很多很多,这里只是根据业务需求添加的。 Card容器,形状设定为圆角矩形,圆角为10%,15dp的内边距,占满所有的宽度,并且长宽比为1.618(没错这是黄金分割比例,老强迫症了) 二、标题部分学过Android framework肯定知道,Android material design里面的CardView是派生自FrameLayout的,也就是一个堆叠视图,而compose里面,Card依然是个堆叠视图,也就是说Card是另外一种Box,所以这里我是直接把标题以Text的可组合函数的形式放到界面上的:
这样就把标题放置在了整个视图的顶部中间。 三、绘制曲线使用Canvas来作为曲线的容器,尺寸铺满整个Card容器:
因为后面绘制曲线需要用到计算曲线上的坐标点,所以这里需要获取到容器的宽高,
这里的高度我给减去了16dp的宽度,是给横轴的文字预留的空间。 如果想完整的绘制每条曲线,这里我们需要获取到所有曲线里面的最大值:
计算每个坐标点,需要根据最大值,当前值,和屏幕的尺寸来计算,所以需要先写两个全局方法:
两个方法都是用总体的尺寸,乘以当前点在所有数据中的比例,就得到了当前点在容器中的位置。 y坐标后面有个0.95的系数,是为了保证最高的数值也给顶部留下5%的控件,看着和谐一点。 然后遍历数据数组中的每个数据点集合:
曲线的核心api是drawPath,所以首先需要一个Path对象,并且移动到第一个数据点的位置:
为了使曲线看上去不那么突兀,圆滑一点,有两种方法: ·使用贝塞尔曲线来绘制 ·使用PathEffect.cornerPathEffect()作为绘制的参数 但是这个drawPath的api里面没有pathEffect这个参数,所以这里只能使用二阶贝塞尔曲线来绘制。 二阶贝塞尔曲线每次绘制一段曲线需要一个控制点和终点,这里我把数据点集合中的上一个坐标点作为控制点,而上一段曲线的的控制点和本段的坐标点的中点作为终点:
使用drawPath将曲线绘制在Canvas上面:
这里style可选项有两个,第一个就是这里使用的Stroke,只会绘制边线;第二个是Fill,会绘制path的整个封闭区域(当然,如果path并不封闭,我没试过是否会自动闭合曲线并绘制整个区域,也懒得去查)。 到这里曲线就会绘制完成了,不过为了好看,我在曲线下方加上了对应于曲线颜色的渐变色,使用的也是drawPath,但是style使用的是Fill,来绘制整个封闭区域。 所以首先要把Path封闭起来,然后才能绘制:
上面首先把path划到曲线空间的最右下角,然后在划到曲线空间的最左下角,再调用close(),整个路径就封闭起来了。然后调用drawPath把整个区域的渐变色绘制出来。渐变色使用的是垂直方向的渐变色,最上面是曲线的颜色,然后不透明度砍半,最下面直接是透明色。 四、绘制横坐标这个地方可以故技重施,使用Text可组合函数把横坐标写到图形的最下面,也就是绘制曲线的时候预留出来的那片空间。 但是之前用xml文件实现Android界面的时候,都知道如果把字体大小设定到12sp以下,Android? studio就会始终警告你12sp以下的观感并不好,还挺烦的,Android开发应该都感受过那种被黄色波浪线支配的恐惧。 当然这里如果用Text可组合函数,我没试过把文字大小改的很小,也不确定是否compose这个时候也会有黄色波浪警告。 另一个不使用Text的原因是精度不够,只能大概的对应横轴坐标的位置。 但是很麻烦的是,jetpack compose Canvas的DrawScope并没有提供drawText接口,所以这里就需要用到上一篇里面提到的api:drawIntoCanvas来调用底层Android Framework的画板来绘制文字。 当然,使用底层Android Framework的画板,首先必不可少的就是一个画笔对象了:
设定为抗锯齿,8dp的字体大小,黑色。 然后确定x轴上字符串的数量以及每个x轴字符串的位置:
这里我设置的是x轴上显示至多七个字符串,太多会显得拥挤,甚至文字都挤到一起去。 然后调用drawIntoCanvas将文字绘制到界面:
上面绘制文字的过程中,很重要的一步就是把绘制文字的具体坐标减去文字长度的一半,使字符串的中心对齐它所表示的x坐标。也就是pointF.x - frameworkPaint.measureText(labels[index]) / 2这一步。 五、绘制纵坐标纵坐标就不能像横坐标一样直接暴力均分了,因为均分出来很可能是一串乱七八糟的数字,想要纵坐标的数字比较和谐,就要把纵坐标的数字都对应到相应的整数,只有前一位或者两位可以是除零以外的整数,其他全是零,所以最关键的一点就是,怎么确定纵坐标的数量级和数量,就是科学计数法里面E后面那个数字是多少。 这里我用取对数的方法获取到y最大值以10为底的对数,也就确定了最大值的数量级。 但是光有数量级也是不行的,万一最大值是1开头的,总不能就绘制一个数值,所以需要根据首位的大小来确定数量级的大小和纵坐标的数量:
这里我选择如果最大值的首位小于4,就将首位乘以10,然后数量级减一,这样就有4到9个纵坐标,根据首位的大小而定。 再由确定的y轴要显示的数字,计算出他们具体在视图中的高度:
然后就可以在画板中画出这些文字和对应的虚线:
绘制y轴文字依然是使用drawIntoCanvas来实现,但是这里需要根据y值相对于1的大小来确定文字对应的字符串。 所以这里首先判断数量级,如果字符串中需要显示小数点,则用String.format方法,将浮点数格式化成我们想要的字符串。 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 17:17:58- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |