目录:javascript
一、前言java
二、背景android
三、组件效果展现git
四、sample解析github
五、library解析post
前言url
本组件是基于安卓平台的图表绘制组件MPAndroidChart( https://github.com/PhilJay/MPAndroidChart),实现了其核心功能的鸿蒙化迁移和重构。目前代码已经开源到(https://gitee.com/isrc_ohos/mpandroid-chart_ohos),欢迎各位下载使用并提出宝贵意见!spa
背景.net
安卓版本的MPAndroidChart在GitHub上有超过3.3万个Star和8.3k个Fork,应该说是目前使用最广,体验最佳的开源图表库。它具绘制折线图、饼图、雷达图等图表的能力,用户只须要本身写一个数据接口,便可实现各类精美数据曲线的绘制,在必定程度上知足了大部分业务的需求。
本组件是MPAndroidChart的鸿蒙化版本,名为MPAndroidChart_ohos,实现了其核心功能。
组件效果展现
目前MPAndroidChart_ohos具备折线图和直方图两种图表绘制能力。下面将分别展现其折线图和直方图的绘制效果。
一、折线图
图1展现了一个由随机数据生成的折线图。MPAndroidChart_ohos继承了原版MPAndroidChart的优秀特性,提供了多种多样的用户自定义接口,例如:
(1) X、Y轴自定义。使用者能够自定义X、Y轴的位置,例如在这个sample里就绘制了左Y轴和上X轴。
(2)辅助线自定义。使用者能够选择是否显示辅助线(或格点线),也能够自由设定辅助线的位置。
(3)图表美化。使用者能够设置图表曲线的各类属性(颜色、粗细等),还能够对曲线包裹区域进行填充。
图1 折线图绘制效果
二、直方图
图2是基于假设场景“2020年1月1日 ~ 15日的小卖部收益状况”绘制的图表。基于这个背景,使用MPAndroidChart_ohos制做了一张直方图。
图2 直方图绘制效果
Sample解析
图3 Sample工程结构
图1和图2主要依靠调用Library中的能力绘制,在Sample中的实现主要由图3中红框所示的两个文件来完成。
若是用户想要绘制图表,只须要完成如下几个步骤便可:
(1)选择图表种类。
(2)设置属性。
(3)导入数据。
一、 选择图表种类
MPAndroidChart_ohos提供了折线图和直方图的绘制能力,使用者只须要根据自身需求选择须要使用的能力便可。
LineChart chart = new LineChart(context); //折线图的初始化 BarChart chart = new BarChart(context); // 直方图的初始化
二、设置属性
MPAndroidChart_ohos提供了图表样式自定义的能力,使用者能够经过调用Library暴露的接口来给图表添加、修改、删除各项属性。例如使用者想要自定义轴线,能够经过实例化XAxis 类的对象,而后经过对象的各类方法实现修改X轴的颜色,设置最大值、最小值等:
XAxis xAxis = chart.getXAxis(); // 实例化 xAxis.setAxisMaximum(20f); //属性设置 xAxis.setAxisMinimum(0f); xAxis.setAxisLineColor(Color.BLACK.getValue());
除了轴线设置之外还能够在图表中加入各类辅助线,例如想要在x = 2处添加一条辅助线,能够经过实例化LimitLine 类的对象,而后经过对象的各类方法实现修改辅助线的宽度、标签位置、文本大小等:
LimitLine llXAxis = new LimitLine(2f, "辅助线:x=2"); // 实例化 llXAxis.setLineWidth(4f); //属性设置 llXAxis.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); llXAxis.setTextSize(10f); llXAxis.setTypeface(Font.DEFAULT);
三、导入数据
在MPAndroidChart_ohos中,不一样类型的图表有着不一样的数据类,例如折线图的数据类为LineData,直方图的数据类为BarData,为何不能仅仅经过一个简单int[]或者float[]做为数据类呢?这是由于在MPAndroidChart_ohos中数据类的做用不只仅是承载数据,同时还须要承载一些图表相关的属性,例如曲线颜色、曲线粗细、数据点颜色、大小等,这样作的意图在后续Library分析时会讲到。
以折线图为例,导入数据的过程以下:
(1)建立LineDataSet类:
LineDataSet set1 = new LineDataSet(values, label);
其中values是使用者想要绘制的一类数据,通常是float[],label是这类数据的标签。
(2)将一类或者几类数据放置到一个ArrayList中
ArrayList<ILineDataSet> dataSets = new ArrayList<>(); dataSets.add(set1);
(3)将ArrayList作成LineData数据类,并传递给chart
LineData data = new LineData(dataSets); chart.setData(data);
Library解析
一、工程结构对比
图 4 MPAndroidChart_ohos(上)与MPAndroidChart (下)的工程结构对比
从图4中的两张图的对比能够看出,MPAndroidChart_ohos是按照MPAndroidChart工程的结构开发的,实现了其主要功能。相较于MPAndroidChart,虽然MPAndroidChart_ohos缺乏exception、highlight、jobs这几个文件夹,但并不影响其主要功能的使用。
二、多设备适配
为了增长多设备适配性,MPAndroidChart内部以dp(density independent pixels)为单位来计算图表中各个部件的相对位置,在绘制图表时,统一将dp数据转化为pixel数据,在这个过程当中就须要系统提供一些显示信息。在安卓中,这些信息由DisplayMetrics来提供,以下代码能够经过上下文获取到DisplayMetrics:
Resources res = context.getResources(); mMetrics = res.getDisplayMetrics();
接下来经过DisplayMetrics能够获取到屏幕的DPI,dp * DPI即为屏幕的pixel:
public static float convertDpToPixel(float dp) { return dp * mMetrics.density; }
在鸿蒙系统中,显示信息经过DisplayAttribute类来获取,如下代码能够获取到DisplayAttribute:
Display display = DisplayManager.getInstance().getDefaultDisplay(this.getContext()).get(); DisplayAttribute displayAttribute = display. getAttributes()
能够看出与安卓仍是有些许不一样的。获得DisplayAttribute后便可获得屏幕DPI,须要注意的是表明DPI的接口与安卓不一样:
public static float convertDpToPixel(float dp) { return dp * mMetrics.densityPixels; }
三、轴线绘制
轴线是一张图的基准,在MPAndroidChart中,轴线甚至做为了图表种类的分类基准!看似MPAndroidChart提供了十余种图表绘制的能力,其实这十余种图表是依托于两种轴线制做的,这两种轴线分别是平面直角坐标系和极坐标系。
在直角坐标系下,MPAndroidChart实现了折线图、散点图、直方图、气泡图、蜡烛图等。
在极坐标系下,MPAndroidChart实现了饼图、雷达图。
在MPAndroidChart_ohos中,和轴线相关的类主要分布在components文件夹和renderer文件夹中:
图5 轴线类与轴线绘制类
其中AxisBase类主要定义了轴应具有的属性,例如颜色、粗细、位置、刻度、标签、最值等。XAxis和YAxis继承自AxisBase,并分别定义了X、Y轴所应具有的属性,例如:X轴的位置属性应是“Top”、“BOTTOM”、“TOP_INSIDE”、“BOTTOM_INSIDE”或“BOTH_SIDED”中的一种;而Y轴与X轴不一样,其位置属性应为“LEFT”或“RIGHT”。
AxisRenderer类是绘制轴线的基类,其定义了绘制轴线所必备的属性和方法,例如用于绘制轴线、标签、辅助线、格点的几种画笔(Paint)和对应的方法接口。XAxisRenderer和YAxisRenderer继承自AxisRenderer,实现了其中用于绘制的接口,真正实现了轴线的绘制。其余的诸如XAxisRenderHorizontalBarChart类从名字上看也容易得知是在一些特殊图表上绘制轴线用的。
四、数据绘制
图6 折线图相关的数据类
在Sample解析中提到对于不一样类型的图表,须要不一样的数据类去承载数据和属性。数据类的继承关系是MPAndroidChart中比较复杂的一部份内容,举一个例子来讲,咱们绘制折线图所需的LineData类,它继承自:
public class LineData extends BarLineScatterCandleBubbleData<ILineDataSet> {
类名有点长,不过不要紧,继续向下寻找:
public abstract class BarLineScatterCandleBubbleData<T extends IBarLineScatterCandleBubbleDataSet<? extends Entry>> extends ChartData<T> {
ChartData类应该就是根了:
public abstract class ChartData<T extends IDataSet<? extends Entry>> {
看似三级继承关系并不算多,可是值得注意的是期间须要实现的接口和泛型参数是很是多的,这些接口和泛型每每还都能继续向下嵌套好多层,这着实给移植工做带来了一些困难。下面来看看这些数据类是作什么的。
ChartData类是数据类的基类,在其中首先定义了数据的上界和下界分别是浮点数所能表明的最大和最小值,同时该类提供了一些数据处理方法,例如若是发现任何数超过了上、下界,都将这些数强制赋值为上、下界,避免溢出带来的数据错误。同时这个类还提供了诸如查询数据点个数、查询数据X、Y值、查询标签、查询最大、最小值等数据查询方法。
BarLineScatterCandleBubbleData和LineData分别是对ChartData的一次和二次封装,自己并无添加任何方法,只是经过实现接口与各类泛型参数对存入其中的数据格式加以限制。
图 7 折线图的绘制类
那么数据点和曲线是如何绘制到图表中的?DataRenderer是数据绘制的基类,其中写出了绘制数据、曲线、标签等的抽象方法。继续以折线图为例,这些抽象方法将在DataRendereràBarLineScatterCandleBubbleRendereràLineScatterCandleRadarRendereràLineRadarRendereràLineChartRenderer这个继承路径中被逐步实现,最终LineChartRenderer实现了绘制折线图的所有能力。
项目贡献人
吴圣垚 郑森文 朱伟 陈美汝 张馨心
做者:朱伟ISRC
想了解更多内容,请访问51CTO和华为合做共建的鸿蒙社区:https://harmonyos.51cto.com