MPAndroidChart setLabelRotationAngle bug

MPAndroidChart setLabelRotationAngle bug
二次蓝 Lv4

MPAndroidChart setLabelRotationAngle bug(应该包括其他关于修改x/y label的bug)

库是好库,但就是不更新了。。

bug 描述:修改 labelRotationAnglesetLabelRotationAngle()),手势缩放一下视图,才触发自动调整视图,会导致图表大小发生变化。用起来就是,第一次显示,label被截断,必须手动缩放一下图表,才能触发视图自适应。

解决过程

上 github 搜一下,也是一个已知陈年老 bug:https://github.com/PhilJay/MPAndroidChart/issues/3298#issuecomment-442241286

谷歌翻译:我尝试旋转标签 xAxis.setLabelRotationAngle(-30f); 这有帮助,但对于第一次渲染它被裁剪,我必须缩放图表以重新渲染,然后显示完整的标签。不知道如何强制初始重新渲染。

继续 github 上看了一个 pr,感觉改的也不好。google 了一圈,没有找到一个很好的不改动库源代码解决方法。

于是自己摸索了下:全文无图(懒

先知道一下某几个方法的意义(基于折线统计图):

mXAxisRenderer.computeAxis():涉及计算 xLabel 的宽高:mXAxis.mLabelRotatedHeightmXAxis.mLabelRotatedWidth

BarLineChartBase.calculateOffsets():涉及计算图表的宽高信息等 ViewPortHandler.mContentRect

调试了下,得到原先大致逻辑:

  1. setDate(),则 notifyDataSetChanged(),触发一次计算 mXAxisRenderer.computeAxis()calculateOffsets()
  2. onDraw 又触发一次 calculateOffsets()mXAxisRenderer.computeAxis() 直接绘制出 x、y 轴,以及上面的 label 标签;
  3. 然后是绘制图上的点,省略。

总结原因:当我们设置 data 的时候,会立即直接计算出对应的 label 宽高信息,而后续我们再设置 xAxis 等轴信息的时候就无法参与计算。导致最后绘图异常。

放大触发原因

手动放大 onTouch 会触发 mChart.calculateOffsets(),该方法会更新 ViewPortHandler.mContentRect 更新 bottom,随后再触发 onDraw

点击不触发原因

点击触发 BarLineChartBase.onDraw -> mXAxisRenderer.computeAxis 更新计算 mXAxis.mLabelRotatedHeightmXAxis.mLabelRotatedWidth;(加上bottom)
并画标签:mXAxisRenderer.renderAxisLabels(canvas);

好像没有重新计算 bottom 重绘啊,忘记了,笔者写此文时也没有验证,以上摘自草稿记录

解决方案

既然知道大致逻辑,那就很好办了。

我们直接先设置好轴信息,再 setDate() 即可!!!

本来是只想先把 setLabelRotationAngle()(即 lineChart.xAxis.labelRotationAngle),放在 setData() 前面。

测试发现高度最终会有些许出入,表现出来也就是旋转后的 label 会有部分被切掉,也就是展示高度虽有变高,但仍不够。

一想,我们对轴做了那么多自定义,那么这个误差也是理所当然的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 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

1
lineChart.setExtraOffsets(10f, 80f, 10f, if (xCount > 25) 10f else 0f)

写文章的时候,没有再调试了,全凭草稿写的,图都懒得弄。仅做一个记录。可能有所纰漏,欢迎指出。
或许可以尝试:https://github.com/AppDevNext/AndroidChart

  • 标题: MPAndroidChart setLabelRotationAngle bug
  • 作者: 二次蓝
  • 创建于 : 2024-04-06 17:17:29
  • 更新于 : 2024-04-06 21:25:00
  • 链接: https://blog.ercilan.cn/2024/04/06/MPAndroidChart-setLabelRotationAngle-bug/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论