花钱做推广广告哪个网站好,网页制作报价模板,手机怎么制作游戏,电商服务站点建设方案1. 引言
电视项目中需要一个折线图表示节电数据变化情况#xff0c;类比 H5 来说#xff0c;Android 中也应该有比较成熟的控件#xff0c;经过调研后#xff0c;发现 MPAndroidChart 功能比较强大#xff0c;网上也有人说可能是目前 Android 开发最好用的一个三方库了类比 H5 来说Android 中也应该有比较成熟的控件经过调研后发现 MPAndroidChart 功能比较强大网上也有人说可能是目前 Android 开发最好用的一个三方库了功能非常强大集成简单。
这里把我的集成使用过程及使用中发现的强大惊喜记录下来留作团队财富可供后续参考。
首先简单的介绍下强大的 MPAndroidChart它支持常用的各种图柱状图横向竖向、线状图多种效果、饼状图、点状图属性也很简单我们使用的时候只需要熟悉控件的 11 各种属性即可。核心功能如下 支持 xy 轴缩放 支持拖拽 支持手指滑动 支持高亮显示 支持保存图表到文件中 支持从文件txt中读取数据 预先定义颜色模板 自动生成标注 支持自定义 xy 轴的显示标签 支持 xy 轴动画 支持 xy 轴设置最大值和附加信息 支持自定义字体颜色背景手势虚线等
2. 集成
集成很简单直接导入作为依赖就可以以下写了一个最小集成的例子主要为了说明步骤
2.1 引入依赖到工程中
// 项目工程的 build.gradle
repositories {maven { url https://jitpack.io }
}// Module的 build.gradle
dependencies {implementation com.github.PhilJay:MPAndroidChart:v3.1.0
}
2.2 Layout 中添加控件
!--节电折线图--
com.github.mikephil.charting.charts.LineChartandroid:idid/chart1android:layout_width0dpandroid:layout_height0dpandroid:layout_alignParentToptrueandroid:layout_alignParentBottomtrueandroid:layout_alignParentStarttrueandroid:layout_alignParentEndtrueandroid:layout_marginTopdimen/tvcommon_px131android:layout_marginBottomdimen/tvcommon_px60android:layout_marginStartdimen/tvcommon_px44android:layout_marginEnddimen/tvcommon_px30 /
2.3 Activity 中使用
// 3.4 节电详情页
mChart findViewById(R.id.chart1)
initChat()
setChatData()
2.3.1 初始化
private fun initChat() {mChart.setBackgroundColor(resources.getColor(R.color.color_00000000))mChart.description.isEnabled false// 2. X 轴样式val xAxis: XAxis mChart.getXAxis()xAxis.setDrawGridLines(false)// xAxis.enableGridDashedLine(10f, 10f, 0f);xAxis.position XAxis.XAxisPosition.BOTTOM// 3. Y轴样式mChart.axisRight.isEnabled false // disable dual axis (only use LEFT axis)var yAxis: YAxis mChart.axisLeftyAxis.axisMaximum 200fyAxis.axisMinimum 0f
}
2.3.2 Activity 中设置数据
public void setChatData(){ListEntry entriesnew ArrayList();ListEntry entries1new ArrayList();entries.add(new Entry(3f,20));entries1.add(new Entry(5f,30));LineDataSet dataSetnew LineDataSet(entries,数据一);LineDataSet dataSet1new LineDataSet(entries1,数据二);ListILineDataSet listnew ArrayList();list.add(dataSet);list.add(dataSet1);LineData lineDatanew LineData(list);mChat.setData(lineData); //将模拟数据用于线形图在线形图显示}
2.3.3 大功告成
3. 使用总结
MPAndroidChart 的强大之处在于它的很多功能都可定制只要你有想法大部分都有解决方法哪怕一时没有只要肯找说不准就能发现。
电视项目中要求的是一个折线图所以这里的使用总结大多集中在折线及我们要实现的效果上其它未涉及的图和属性暂时不写后续使用的时候再作探索及总结。
3.1 整体功能及专业术语一览网上找的一张图镇楼哈哈 3.2 基础设置 非数据类型在初始化时设置
首先在 initChat函数中进行了一些基础设置把一些用不到的功能关闭
private fun initChat() {mChart.setBackgroundColor(resources.getColor(R.color.color_00000000))mChart.description.isEnabled falsemChart.setTouchEnabled(false)mChart.setDrawGridBackground(false)mChart.isDragEnabled falsemChart.setScaleEnabled(false)mChart.setPinchZoom(false)mChart.legend.isEnabled false
}
3.3 x、y 轴设置 非数据类型在初始化时设置
这个也不属于数据设置所以在初始化时进行如下分别进行了线宽线颜色Label 的字体大小、颜色、还有网格线
private fun initChat() {...// 2. X 轴样式val xAxis: XAxis mChart.getXAxis()xAxis.setDrawGridLines(false)// xAxis.enableGridDashedLine(10f, 10f, 0f);xAxis.position XAxis.XAxisPosition.BOTTOMxAxis.axisLineWidth resources.getDimension(R.dimen.tvcommon_px1)xAxis.axisLineColor resources.getColor(R.color.color_979797)xAxis.textSize resources.getDimension(R.dimen.tvcommon_sp16)xAxis.textColor resources.getColor(R.color.white_60alpha)xAxis.valueFormatter object : ValueFormatter() {override fun getAxisLabel(value: Float, axis: AxisBase?): String {// 自定义 X 轴显示内容return super.getAxisLabel(value, axis) 月}}// 3. Y轴样式mChart.axisRight.isEnabled false // disable dual axis (only use LEFT axis)var yAxis: YAxis mChart.axisLeftyAxis.axisLineWidth resources.getDimension(R.dimen.tvcommon_px1)yAxis.axisLineColor resources.getColor(R.color.color_979797)yAxis.textSize resources.getDimension(R.dimen.tvcommon_sp16)yAxis.textColor resources.getColor(R.color.white_60alpha)yAxis.setDrawGridLines(true) // horizontal grid linesyAxis.enableGridDashedLine(resources.getDimension(R.dimen.tvcommon_px6),resources.getDimension(R.dimen.tvcommon_px6),0f)yAxis.axisMaximum 200fyAxis.axisMinimum 0f
}
3.4 折线类型设置
需要在 填充数据时给 LineDataSet 设置一个 mode如下
private fun setChatData() {...val set1 LineDataSet(values, DataSet 1)set1.mode LineDataSet.Mode.HORIZONTAL_BEZIER // 折线类型
}
setModeLineDataSet.Mode mode设置模式有四种 1.CUBIC_BEZIER 立方曲线 2.LINEAR 直线 3.STEPPED 阶梯 4.HORIZONTAL_BEZIER 水平曲线
电视项目这里需要的是一个曲线所以设置为 HORIZONTAL_BEZIER
3.5 顶点设置
顶点可进行 icon 绘制、小圆点实心/空心、自定义值显示
private fun setChatData() {...val set1 LineDataSet(values, DataSet 1)set1.mode LineDataSet.Mode.HORIZONTAL_BEZIER // 折线类型// 顶点set1.setValueFormatter(object : ValueFormatter() {override fun getFormattedValue(value: Float): String {return // 这里返回空即顶点不显示值否则不太好看}})set1.valueTextSize resources.getDimension(R.dimen.tvcommon_sp12)set1.setDrawIcons(false) // 不显示端点的iconset1.setDrawCircles(false) // 显示顶点圆quanset1.setDrawCircleHole(true) // 空心还是实心
}
3.6 折线及填充设置
private fun setChatData() {...// 折线set1.color resources.getColor(R.color.blue_gray_32B5E6)set1.setCircleColor(resources.getColor(R.color.blue_gray_32B5E6))set1.lineWidth resources.getDimension(R.dimen.tvcommon_px2)set1.circleRadius resources.getDimension(R.dimen.tvcommon_px4)// 折线包裹起来的区域set1.fillFormatter IFillFormatter { dataSet, dataProvider - mChart.getAxisLeft().getAxisMinimum() }if (Utils.getSDKInt() 18) {// drawables only supported on api level 18 and aboveval drawable ContextCompat.getDrawable(this, R.drawable.shape_chat_fill_blue)set1.fillDrawable drawable} else {set1.fillColor R.color.blue_gray_32B5E6}set1.setDrawFilled(true)
}
3.7 X 轴自定义显示 非数据类型在初始化时设置
再回到 X 轴由于项目要求X 轴要显示节电的日期但是构造数据时只是一个数组默认显示的是数组的下标所以这里需要自定义
private fun initChat() {... // 2. X 轴样式val xAxis: XAxis mChart.getXAxis()...xAxis.valueFormatter object : ValueFormatter() {override fun getAxisLabel(value: Float, axis: AxisBase?): String {// 自定义 X 轴显示内容这里可以通过 axis 中的 postion 从数据中进行一个映射找到它对应的日期return super.getAxisLabel(value, axis) 月}}
}
4. 踩坑及解决
4.1 宽度或 margin 跟自己设置的不一样
1. 效果出来后发现最右侧不是我设置的比我预计的靠左了离边比较远达不到 UI 设计的效果如下 2. 这里的设置应该不是通过简单的 XML 位置属性就能修改的了因为这属于 MPAndroidChat 控件的内部了所以得深入 MPAndroidChat找到产生间隙的原因于是开始翻源码
3. 经过翻阅源码得知它内部有一个 minOffset
Override
public void calculateOffsets() {...float minOffset Utils.convertDpToPixel(mMinOffset);mViewPortHandler.restrainViewPort(Math.max(minOffset, offsetLeft),Math.max(minOffset, offsetTop),Math.max(minOffset, offsetRight),Math.max(minOffset, offsetBottom));...
}
public void setMinOffset(float minOffset) {mMinOffset minOffset;
} 再往下查原来 mMinOffset是可能通过 setMinOffset设置进去的所以在我们的代码 initChat中添加上一行再看效果OK 啦
private fun initChat() {...mChart.minOffset 0f...
}
4.2 设置 x 轴的 Label 后发现最底下一层有一点显示不全被截断了如下 1. 分析原因
1这个应该也是 MPAndroidChat 内部实现导致的修改外部 Layout 中的 margin padding 应该不生效果然试过之后没有生效问题依旧
216sp 时显示是这个效果而缩小字号后比如 12sp 就没有问题能够显示猜测是它内部写死了一个距离但看源码内的相关说明它的高度是自动计算的如下
/*** Class representing the x-axis labels settings. Only use the setter methods to* modify it. Do not access public variables directly. Be aware that not all* features the XLabels class provides are suitable for the RadarChart.** author Philipp Jahoda*/
public class XAxis extends AxisBase {/*** width of the x-axis labels in pixels - this is automatically* calculated by the computeSize() methods in the renderers*/public int mLabelWidth 1;/*** height of the x-axis labels in pixels - this is automatically* calculated by the computeSize() methods in the renderers*/public int mLabelHeight 1;
3按理说不应该出现这种情况难道是 MPAndroidChat 的 Bug是不是高版本就好了呢于是上网查了一下https://gitee.com/jiangsongbai/MPAndroidChart Github 打不开到这里的一个 fork 上看一下发现我用的已经是最新版了 v3.1.0 吐槽版本号竟然带个 v看来不专业啊 4小插曲由于项目中使用的是 dimen 中定义的 tvcommon_sp16在不同分辨率下可能不一样我原先是写死的抱着一点小希望在代码中使用 dimen 试一下期望字体能够变小一点不触发此问题结果又失望了
xAxis.textSize resources.getDimension(R.dimen.tvcommon_sp16)
2. extraBottomOffset
1再翻阅源码还是在 BarLineChatBase.java 中的 calculateOffsets 函数发现了端倪如下
Override
public void calculateOffsets() {....offsetTop getExtraTopOffset();offsetRight getExtraRightOffset();offsetBottom getExtraBottomOffset();offsetLeft getExtraLeftOffset();float minOffset Utils.convertDpToPixel(mMinOffset);mViewPortHandler.restrainViewPort(Math.max(minOffset, offsetLeft),Math.max(minOffset, offsetTop),Math.max(minOffset, offsetRight),Math.max(minOffset, offsetBottom));....
}
2这里有一个 getExtraBottomOffset再往下看它是在基类 chat.java 中有一个 mExtraBottomOffset
/*** return the extra offset to be appended to the viewports bottom*/
public float getExtraBottomOffset() {return mExtraBottomOffset;
}
3看注释像是有点用尝试一下
private fun initChat() {....mChart.minOffset 0fmChart.extraBottomOffset resources.getDimension(R.dimen.tvcommon_px2) // 因为X轴的Label字体设为 16sp 后最底下有一点显示不全需要在这里打上一个小补丁。....
}
4大功告成 4.3 顶点的数据显示想要隔位置显示效果
跟产品讨论的时候把 UI 原先设计的选中点的值显示出来的效果去掉了因为电视上没有触摸通过遥控器交互暂时先不做选中效果如果显示出来所有的数据会显得比较凌乱所以想进行隔几个显示或什么效果研究后发现重截函数中没有位置信息无法进行计算是哪一个 postion暂时无法做到不同的效果只能统一显示或不显示后续再进行深入研究看是否能够做到
private fun setChatData() {...val set1 LineDataSet(values, DataSet 1)set1.mode LineDataSet.Mode.HORIZONTAL_BEZIER // 折线类型// 顶点set1.setValueFormatter(object : ValueFormatter() {override fun getFormattedValue(value: Float): String {return // 这里返回空即顶点不显示值否则不太好看}})...
}
5. 小结
这里记录了在电视项目中使用 MPAndroidChat 的一些使用心得重点集中在折线上通过对它的各种属性进行修改自定义了自己的 UI 界面达到与 UI 设计图一样的效果也发掘出了 minOffset、extraBottomOffset 这样的小众属性的使用场景及效果希望能够引起大家的一些共鸣发现问题时快速找到解决方法。
6. 团队介绍
「三翼鸟数字化技术平台-场景设计交互平台」主要负责设计工具的研发包括营销设计工具、家电VR设计和展示、水电暖通前置设计能力研发并沉淀素材库构建家居家装素材库集成户型库、全品类产品库、设计方案库、生产工艺模型打造基于户型和风格的AI设计能力快速生成算量和报价同时研发了门店设计师中心和项目中心包括设计师管理能力和项目经理管理能力。实现了场景全生命周期管理同时为水空气厨房等产业提供商机管理工具从而实现了以场景贯穿的B端C端全流程系统。