給Android圖表庫MPAndroidChart的坐標換行
做統計圖時,經常會有這樣的需求:x坐標需要換行顯示,日和月或者是月和年需要分兩行顯示。但是找遍MPAndroidChart的各種教程,好像也沒有相關的方法可以實現......
以LineChart為例,我們想要的效果是類似這樣子的:
首先,MPAndroidChart確實是沒有提供更改坐標換行顯示的方法。在看這篇文章之前,你可能已經嘗試過實現一個ValueFormatter,或者是"\r\n"這樣的掙扎,發現并沒有什么卵用。但就算真給你換行了,如何居中,如何設置兩行不同字體也是問題。
咋辦?看一下源碼吧。看看設進去的數據是如何顯示出來的。
我們是這樣來設置坐標軸要顯示的內容的:
LineData data = new LineData(xValues, dataSets);
mChart.setData(data);
mChart.invalidate();
跟著setData方法進源碼,一路經過Chart,BarLineChartBase,最終來到了XAxisRenderer這個類,我們的xValues被賦值給了它的mXAxis。然后,好像就沒有然后了......
不對,別忘了我們setData之后還調用了invalidate方法請求重繪,重繪會去調用Chart的onDraw方法。再看看繼承Chart的BarLineChartBase,它的onDraw方法里出現了這一句:
this.mXAxisRenderer.renderGridLines(canvas);
感覺離真相越來越近了。我們再跟著這個方法進來,看到里面調用了drawLabels方法,然后drawLabels又調用了drawLabel方法,最終我們來到了這里:
protected void drawLabel(Canvas c, String label, int xIndex, float x, float y, PointF anchor,float angleDegrees) {
String formattedLabel = mXAxis.getValueFormatter().getXValue(label, xIndex,mViewPortHandler);
Utils.drawXAxisValue(c, formattedLabel, x, y, mFirstLinePaint, anchor, angleDegrees);
}
最后進入Utils.drawXAxisValue方法,終于看到了這樣的一句:
c.drawText(text, drawOffsetX, drawOffsetY, paint);
哎呦我去,終于找到了,藏這么深。
可以看到坐標軸是用Canvas.drawText顯示出來的。了解一下你會發現,通常情況下,drawText方法是不支持"\n\r"的。看來我們只要改drawLabel這個方法就可以了。由于源碼幾個類的耦合程度比較高,我并沒有找到可以通過繼承重寫的方法實現,不得已只好改源代碼了。
我修改后的代碼是這樣的:
protected void drawLabel(Canvas c, String label, int xIndex, float x, float y, PointF anchor, float angleDegrees) {
String formattedLabel = mXAxis.getValueFormatter().getXValue(label, xIndex, mViewPortHandler);
float labelHeight = mXAxis.getTextSize();
float labelInterval = 25f;
String[] labels = label.split(" ");
Paint mFirstLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFirstLinePaint.setColor(Color.WHITE);
mFirstLinePaint.setTextAlign(Align.CENTER);
mFirstLinePaint.setTextSize(Utils.convertDpToPixel(15f));
mFirstLinePaint.setTypeface(mXAxis.getTypeface());
Paint mSecondLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mSecondLinePaint.setColor(0xFF9b9b9b);
mSecondLinePaint.setTextAlign(Align.CENTER);
mSecondLinePaint.setTextSize(Utils.convertDpToPixel(10f));
mSecondLinePaint.setTypeface(mXAxis.getTypeface());
if (labels.length > 1) {
Utils.drawXAxisValue(c, labels[0], x, y, mFirstLinePaint, anchor, angleDegrees);
Utils.drawXAxisValue(c, labels[1], x, y + labelHeight + labelInterval, mSecondLinePaint, anchor, angleDegrees);
} else {
Utils.drawXAxisValue(c, formattedLabel, x, y, mFirstLinePaint, anchor, angleDegrees);
}
}
我在要分行顯示的字符串間加了個空格,在這里再用空格切割成兩個字符串。我們可以分別給兩行設置不同的格式,并且讓他們都居中顯示。最后繪制的時候,把第二行的y坐標改一下,在第一行的基礎上加上一定的高度就可以了。妥妥的。
另外,那條黃色的高亮線也是改源碼實現的。
來自:http://www.jianshu.com/p/e616546c8d21