MPAndroidChart setLabelRotationAngle bug
MPAndroidChart setLabelRotationAngle bug(应该包括其他关于修改x/y label的bug)
库是好库,但就是不更新了。。
bug 描述:修改 labelRotationAngle(setLabelRotationAngle()),手势缩放一下视图,才触发自动调整视图,会导致图表大小发生变化。用起来就是,第一次显示,label被截断,必须手动缩放一下图表,才能触发视图自适应。
解决过程
上 github 搜一下,也是一个已知陈年老 bug:https://github.com/PhilJay/MPAndroidChart/issues/3298#issuecomment-442241286
谷歌翻译:我尝试旋转标签
xAxis.setLabelRotationAngle(-30f); 这有帮助,但对于第一次渲染它被裁剪,我必须缩放图表以重新渲染,然后显示完整的标签。不知道如何强制初始重新渲染。
继续 github 上看了一个 pr,感觉改的也不好。google 了一圈,没有找到一个很好的不改动库源代码解决方法。
于是自己摸索了下:全文无图(懒
先知道一下某几个方法的意义(基于折线统计图):
mXAxisRenderer.computeAxis():涉及计算 xLabel 的宽高:mXAxis.mLabelRotatedHeight、mXAxis.mLabelRotatedWidth
BarLineChartBase.calculateOffsets():涉及计算图表的宽高信息等ViewPortHandler.mContentRect。
调试了下,得到原先大致逻辑:
setDate(),则notifyDataSetChanged(),触发一次计算mXAxisRenderer.computeAxis()、calculateOffsets();onDraw又触发一次calculateOffsets()、mXAxisRenderer.computeAxis()直接绘制出 x、y 轴,以及上面的 label 标签;- 然后是绘制图上的点,省略。
总结原因:当我们设置 data 的时候,会立即直接计算出对应的 label 宽高信息,而后续我们再设置 xAxis 等轴信息的时候就无法参与计算。导致最后绘图异常。
放大触发原因
手动放大 onTouch 会触发 mChart.calculateOffsets(),该方法会更新 ViewPortHandler.mContentRect 更新 bottom,随后再触发 onDraw。
点击不触发原因
点击触发 BarLineChartBase.onDraw -> mXAxisRenderer.computeAxis 更新计算 mXAxis.mLabelRotatedHeight、mXAxis.mLabelRotatedWidth;(加上bottom)
并画标签:mXAxisRenderer.renderAxisLabels(canvas);
好像没有重新计算 bottom 重绘啊,忘记了,笔者写此文时也没有验证,以上摘自草稿记录
解决方案
既然知道大致逻辑,那就很好办了。
我们直接先设置好轴信息,再 setDate() 即可!!!
本来是只想先把
setLabelRotationAngle()(即lineChart.xAxis.labelRotationAngle),放在setData()前面。测试发现高度最终会有些许出入,表现出来也就是旋转后的 label 会有部分被切掉,也就是展示高度虽有变高,但仍不够。
一想,我们对轴做了那么多自定义,那么这个误差也是理所当然的。
// kotlin举例
fun constructChart(analyzedData: AnalyzedData) {
lineChart.tag = analyzedData
lineChart.description.text = "数据图表"
lineChart.description.yOffset = 22f
lineChart.description.textColor = colorBoarder
lineChart.setNoDataText("暂无数据")
lineChart.setNoDataTextColor(primaryColor)
val xCount = 999f
// 设置 X 轴
val xAxis = lineChart.xAxis
xAxis.axisMaximum = xCount
xAxis.axisMinimum = 0f
xAxis.position = XAxis.XAxisPosition.BOTTOM
xAxis.setDrawAxisLine(false)
xAxis.setDrawGridLines(false)
// 设置数量
xAxis.setLabelCount(xCount.toInt())
xAxis.valueFormatter = analyzedData
xAxis.textColor = colorBoarder
xAxis.isGranularityEnabled = true
xAxis.setGranularity(1f)
lineChart.xAxis.labelRotationAngle = when {
xCount > 25f -> -90f
xCount > 13f -> -45f
else -> 0f
}
// 设置 Y 轴
val yRightAxis = lineChart.axisRight
yRightAxis.axisMaximum = analyzedData.ceilMaxY
yRightAxis.axisMinimum = 0f
LogUtils.log("YAxisMaximum: ${yRightAxis.axisMaximum}")
yRightAxis.setDrawGridLines(true)
yRightAxis.enableGridDashedLine(15f, 5f, 0f)
yRightAxis.textColor = colorBoarder
yRightAxis.isGranularityEnabled = true
yRightAxis.setGranularity(1f)
val yLeftAxis = lineChart.axisLeft
yLeftAxis.axisMaximum = analyzedData.ceilMaxY
yLeftAxis.axisMinimum = 0f
yLeftAxis.setDrawLabels(false)
yLeftAxis.setDrawGridLines(false)
lineChart.animateXY(600, 600, Easing.EaseInSine, Easing.EaseInSine)
// 设置图例
val legend: Legend = lineChart.legend
legend.isEnabled = false
// 最后设置数据,第一次设置时也会触发notifyDataSetChanged,重新计算
lineChart.data = analyzedData.lineData
}
最后,此外如果自动计算并没有全部显示 label,可以尝试设置额外 offset
lineChart.setExtraOffsets(10f, 80f, 10f, if (xCount > 25) 10f else 0f)
写文章的时候,没有再调试了,全凭草稿写的,图都懒得弄。仅做一个记录。可能有所纰漏,欢迎指出。
或许可以尝试:https://github.com/AppDevNext/AndroidChart

浙公网安备 33010602011771号