給Android圖表庫MPAndroidChart的坐標換行

RaleighKinc 7年前發布 | 15K 次閱讀 安卓開發 Android開發 移動開發

做統計圖時,經常會有這樣的需求: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

 

 本文由用戶 RaleighKinc 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!