基於MPAndroidChart的自定義LineChart(一)----節點繪製叉號+分段繪製背景

MPAndroidChart是Android平臺上一款強大易用的圖表庫,支持線狀圖、柱狀圖、散點圖等八種圖表類型和縮放、拖動(平移)、選擇等手勢,還支持動畫和高亮等功能。但是別人給好的功能畢竟只能滿足一般功能,一個程序員最基本的能力就應該是根據需求做出自定義的功能了,這裏我對MPAndroidChart進行一些改造,MPAndroidChart只能在節點繪製圓形,現在要給它加上繪製叉號的功能。另外,本來MPAndroidChart的背景只能設置整個一大塊背景,現在我加上了按行設置背景色的功能。

效果如圖:

節點的細節部分:

功能實現

繼承LineChart

自定義LineChart的第一步是要繼承LineChart,實現其構造方法。然後重寫onDraw方法,在onDraw方法中,再繪製背景,繪製叉號,繪製圖表。這裏要注意繪製的順序,從下到上,一層層疊加。

    /**
     * 重寫onDraw方法,注意繪製順序,先繪製背景色,再繪製叉號,最後繪製圖表
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        drawBgColor(canvas);
        drawCross(canvas);
        super.onDraw(canvas);
        Log.i(TAG, "onDraw");
    }

畫背景

爲了讓代碼看起來更直觀,我先創建了一個類BgColor,其中包含start,stop和color三個屬性。

/**
 * Created by xiaoniu on 2017/4/10.
 * BgColor是設置背景的單位,創建時需要傳入起點和終點的值,還有要設置的顏色
 * 如要把縱座標20-40的背景設爲紅色,就新建一個BgColor
 * new BgColor(20,40,Color.RED)
 */

public class BgColor {

    /**
     * @param start 起始點
     * @param stop 結束點
     * @param color 顏色
     */
    public BgColor( float start, float stop,int color) {
        this.start = stop;
        this.stop = start;
        this.color = color;
    }

    private float start;
    private float stop;
    private int color;

    public float getStart() {
        return start;
    }

    public void setStart(float start) {
        this.start = start;
    }

    public float getStop() {
        return stop;
    }

    public void setStop(float stop) {
        this.stop = stop;
    }

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }
}

三個屬性分別對應起始點,結束點和顏色。然後將自己需要設置的背景都放到一個List中。

    /**
     * 分段背景設置
     * @return 每條背景的組合
     */
    private ArrayList<BgColor> getBg() {
        ArrayList<BgColor> bgList = new ArrayList<>();

        bgList.add(new BgColor(10, 20, Color.YELLOW));//參數信息:縱座標從0到20設置顏色爲黃色
        bgList.add(new BgColor(20, 40, 0xFF00FF00));//支持16進制顏色
        bgList.add(new BgColor(40, 70, Color.BLUE));
        bgList.add(new BgColor(70, 80, Color.RED));
        return bgList;
    }

別忘了給圖表設置繪製背景的屬性,之後再把數據傳給圖表。

//給表格背景添加顏色
mChart.setDrawBgColor(true);
//設置背景顏色的屬性
mChart.setBgColor(getBg());

而在自定義LineChart的drawBgColor方法中,就是從List中取出每個BgColor,獲得其start和stop,再根據MPAndroidChart提供的能夠將圖表上的值轉換爲像素座標點的方法getPixelForValues,得到需要繪製背景的左下角和右上角的座標,用canvas畫矩形就可以了。

private void drawBgColor(Canvas canvas) {
        if (enableDrawBgColor) {
            if (!bgList.isEmpty()) {
                Paint paint = new Paint();
                for (BgColor r : bgList
                        ) {
                    MPPointD pStart = this.getPixelForValues(this.getXChartMin(), r.getStart(), YAxis.AxisDependency.LEFT);//左下角
                    MPPointD pStop = this.getPixelForValues(this.getXChartMax(), r.getStop(), YAxis.AxisDependency.LEFT);//右上角
                    paint.setColor(r.getColor());
                    canvas.drawRect(new RectF((float) pStart.x, (float) pStart.y, (float) pStop.x, (float) pStop.y), paint);
                }
            }else {
                Log.i(TAG, "No BgColor to Draw");
            }
        }
    }

畫叉號

畫叉號之前要得到節點的數據,同樣是利用getPixelForValues將圖表上的值轉化爲像素座標點

private void drawCross(Canvas canvas) {

        if (enableDrawCross) {
            if (this.getData() != null) {
                LineDataSet set = (LineDataSet) this.getData().getDataSetByIndex(0);
                list = set.getValues();
                set.setDrawCircles(false);
                LineData data = new LineData(set);
                this.setData(data);
                for (Entry e : list
                        ) {
                    MPPointD p = this.getPixelForValues(e.getX(), e.getY(), YAxis.AxisDependency.LEFT);
                    drawNode(canvas, (float) p.x, (float) p.y);
                }
            }else{
                Log.i(TAG, "No Data to Draw");
            }
        }
    }

畫叉號就是繪製兩個互相垂直的直線,有了像素座標點和canvas也就很簡單了。

    private void drawNode(Canvas canvas, float x, float y) {
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(crossWidth);
        canvas.drawLine(x - crossLength / 2, y - crossLength / 2, x + crossLength / 2, y + crossLength / 2, paint);
        canvas.drawLine(x - crossLength / 2, y + crossLength / 2, x + crossLength / 2, y - crossLength / 2, paint);
    }

END

細節比較粗糙,以後再完善,歡迎評論交流。

最後附上github代碼:https://github.com/xiaoniu/CrossNodeLineChart

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章