Android 折線圖表MPAndroidChart的實(shí)現(xiàn)

昨日夜觀天象,今日忽見北斗星隕落,《Android 折線圖表》應(yīng)運(yùn)而生。


single.png

many.png

一.本篇采用MPAndroidChart,大體實(shí)現(xiàn)步驟可分為兩步:

  1.配置基本屬性(包括X,Y軸)
  2.設(shè)置折線數(shù)據(jù)并添加

二.
第一步,配置基本屬性。

1.依賴:

      當(dāng)前工程Build.gradle里: implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
      項(xiàng)目Build.gradle里:

            allprojects {
                  repositories {
                  maven { url "https://jitpack.io" }
                  }
            }

2.配置圖表控件的基本屬性:

/**
 * 設(shè)置Chart的一些基本配置
 */
private void initChart() {
    //配置基本信息
    lineChart.getDescription().setEnabled(false);   //設(shè)置描述
    lineChart.setTouchEnabled(true);    //設(shè)置是否可以觸摸
    lineChart.setDragDecelerationFrictionCoef(0.9f);    //設(shè)置滾動(dòng)時(shí)的速度快慢
    lineChart.setDragEnabled(true);     // 是否可以拖拽
    lineChart.setScaleXEnabled(false);   //設(shè)置X軸是否能夠放大
    lineChart.setScaleYEnabled(false);  //設(shè)置Y軸是否能夠放大
    //lineChart.setScaleEnabled(true);    // 是否可以縮放 x和y軸, 默認(rèn)是true
    lineChart.setDrawGridBackground(false);//設(shè)置圖表內(nèi)格子背景是否顯示,默認(rèn)是false
    lineChart.setHighlightPerDragEnabled(true);//能否拖拽高亮線(數(shù)據(jù)點(diǎn)與坐標(biāo)的提示線),默認(rèn)是true
    lineChart.setBackgroundColor(Color.WHITE);  //設(shè)置背景顏色

    //配置X軸屬性
    xAxis = lineChart.getXAxis();

    //xAxis.setLabelRotationAngle(25f);  //設(shè)置旋轉(zhuǎn)偏移量
    xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);  //設(shè)置X軸的位置
    //設(shè)置標(biāo)簽文本格式
    xAxis.setTextSize(10f);
    //設(shè)置標(biāo)簽文本顏色
    xAxis.setTextColor(Color.rgb(255, 192, 56));
    //是否繪制軸線
    xAxis.setDrawAxisLine(true);
    //是否繪制網(wǎng)格線
    xAxis.setDrawGridLines(false);
    //設(shè)置是否一個(gè)格子顯示一條數(shù)據(jù),如果不設(shè)置這個(gè)屬性,就會(huì)導(dǎo)致X軸數(shù)據(jù)重復(fù)并且錯(cuò)亂的問題
    xAxis.setGranularity(1f);

    //配置Y軸信息
    leftAxis = lineChart.getAxisLeft();
    leftAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);   //設(shè)置Y軸的位置
    leftAxis.setDrawGridLines(true);    //設(shè)置左邊的網(wǎng)格線顯示
    leftAxis.setGranularityEnabled(false);//啟用在放大時(shí)限制y軸間隔的粒度特性。默認(rèn)值:false。
    leftAxis.setTextColor(Color.rgb(255, 192, 56)); //設(shè)置Y軸文字顏色

    YAxis rightAxis = lineChart.getAxisRight(); //獲取右邊的Y軸
    rightAxis.setEnabled(false);   //設(shè)置右邊的Y軸不顯示

    //設(shè)置圖例(也就是曲線的標(biāo)簽)
    Legend legend = lineChart.getLegend();//設(shè)置比例圖
    legend.setEnabled(false);   //因?yàn)樽詭У膱D例太丑,而且操作也不方便,樓主選擇自定義,設(shè)置不顯示比例圖
}

第二步,設(shè)置折線數(shù)據(jù)。

首先,自定義我們的X軸適配器:

public class MyXFormatter  implements IAxisValueFormatter {

private List<String> list;

public MyXFormatter(List<String> values) {
    this.list = values;
}

private static final String TAG = "MyXFormatter";

@Override
public String getFormattedValue(float value, AxisBase axis) {
    // "value" represents the position of the label on the axis (x or y)
    Log.d(TAG, "----->getFormattedValue: " + value) ;
    if (value<list.size()){
        return list.get((int) (value));
    }else {
        return null;
    }
  }
}

然后,設(shè)置折線數(shù)據(jù)。單條折線的數(shù)據(jù)方法設(shè)置如下:

/**
 * 設(shè)置單條折線的數(shù)據(jù)
 * count 單條折線的數(shù)據(jù)量
 */
private void setSingleDatas(int count) {
    //設(shè)置單條折線的X軸數(shù)據(jù)
    singleNameList = new ArrayList<>();
    for (int i = 0; i < count; i++) {
        int j = i+1;
        singleNameList.add(j + "月");
    }
    //將X軸數(shù)據(jù)傳入自定義的X軸ValueFormatter
    MyXFormatter formatter = new MyXFormatter(singleNameList);
    xAxis.setValueFormatter(formatter);

    //設(shè)置單條折現(xiàn)的Y軸數(shù)據(jù)
    ArrayList<Entry> yList = new ArrayList<Entry>();
    for (int i = 0; i < count; i++) {
       float value = (float) (Math.random()*100);
       yList.add(new Entry(i,value));
    }

    LineDataSet lineDataSet = new LineDataSet(yList, "單條折線");   //設(shè)置單條折線
    ArrayList<ILineDataSet> dataSets = new ArrayList<>();
    //設(shè)置折線的屬性
    lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);   //設(shè)置左右兩邊Y軸節(jié)點(diǎn)描述
    lineDataSet.setValueTextColor(ColorTemplate.getHoloBlue()); //設(shè)置節(jié)點(diǎn)文字顏色
    lineDataSet.setDrawCircles(false);  //設(shè)置是否顯示節(jié)點(diǎn)的小圓點(diǎn)
    lineDataSet.setDrawValues(false);       //設(shè)置是否顯示節(jié)點(diǎn)的值
    lineDataSet.setHighLightColor(Color.rgb(244, 117, 117));//當(dāng)點(diǎn)擊節(jié)點(diǎn)時(shí),將會(huì)出現(xiàn)與節(jié)點(diǎn)水平和垂直的兩條線,可以對(duì)其進(jìn)行定制.此方法為設(shè)置線條顏色
    lineDataSet.setHighlightEnabled(true);//設(shè)置是否顯示十字線
    lineDataSet.setColor(Color.BLUE);    //設(shè)置線條顏色
    lineDataSet.setCircleColor(Color.WHITE);  //設(shè)置節(jié)點(diǎn)的圓圈顏色
    lineDataSet.setLineWidth(1f);   //設(shè)置線條寬度
    lineDataSet.setCircleRadius(4f);//設(shè)置每個(gè)坐標(biāo)點(diǎn)的圓大小
    lineDataSet.setDrawCircleHole(false);//是否定制節(jié)點(diǎn)圓心的顏色,若為false,則節(jié)點(diǎn)為單一的同色點(diǎn),若為true則可以設(shè)置節(jié)點(diǎn)圓心的顏色
    lineDataSet.setValueTextSize(9f);   //設(shè)置 DataSets 數(shù)據(jù)對(duì)象包含的數(shù)據(jù)的值文本的大小(單位是dp)。
    //設(shè)置折線圖填充
    lineDataSet.setDrawFilled(false);    //Fill填充,可以將折線圖以下部分用顏色填滿
    lineDataSet.setFillAlpha(65);       ////設(shè)置填充區(qū)域透明度,默認(rèn)值為85
    lineDataSet.setFillColor(ColorTemplate.getHoloBlue());//設(shè)置填充顏色
    lineDataSet.setFormLineWidth(1f);
    lineDataSet.setFormSize(15.f);

    dataSets.add(lineDataSet);

    LineData data = new LineData(dataSets);
    lineChart.setData(data);    //添加數(shù)據(jù)
}

多條折線的數(shù)據(jù)設(shè)置方法如下:

/**
 * 設(shè)置多條折線的數(shù)據(jù)
 * @param chartData //線條x軸的個(gè)數(shù)
 * @param count     //線條的個(gè)數(shù)
 */
private void setManyDatas(int chartData, int count) {
    singleNameList = new ArrayList<>();
    for (int i = 0; i < chartData; i++) {
        int j = i+1;
        singleNameList.add(j + "月");
    }
    MyXFormatter formatter = new MyXFormatter(singleNameList);
    xAxis.setValueFormatter(formatter);

    initChartColors();  //設(shè)置線條顏色集合
    initChartNames(count);   //設(shè)置不同線條名字的集合
    ArrayList<ILineDataSet> dataSets = new ArrayList<>();   //線條數(shù)據(jù)集合

    for (int i = 0; i < count; i++) {
        //設(shè)置單條折現(xiàn)的Y軸數(shù)據(jù)
        ArrayList<Entry> yList = new ArrayList<Entry>();
        for (int j = 0; j < chartData; j++) {
            float value = (float) (Math.random()*100);
            yList.add(new Entry(j,value));
        }

        LineDataSet lineDataSet = new LineDataSet(yList, nameList.get(i));   //設(shè)置單條折線
        //設(shè)置折線的屬性
        lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);   //設(shè)置左右兩邊Y軸節(jié)點(diǎn)描述
        lineDataSet.setValueTextColor(ColorTemplate.getHoloBlue()); //設(shè)置節(jié)點(diǎn)文字顏色
        lineDataSet.setDrawCircles(false);  //設(shè)置是否顯示節(jié)點(diǎn)的小圓點(diǎn)
        lineDataSet.setDrawValues(false);       //設(shè)置是否顯示節(jié)點(diǎn)的值
        lineDataSet.setHighLightColor(Color.rgb(244, 117, 117));//當(dāng)點(diǎn)擊節(jié)點(diǎn)時(shí),將會(huì)出現(xiàn)與節(jié)點(diǎn)水平和垂直的兩條線,可以對(duì)其進(jìn)行定制.此方法為設(shè)置線條顏色
        lineDataSet.setHighlightEnabled(true);//設(shè)置是否顯示十字線
        lineDataSet.setColor(colours.get(i));    //設(shè)置線條顏色
        lineDataSet.setCircleColor(Color.WHITE);  //設(shè)置節(jié)點(diǎn)的圓圈顏色
        lineDataSet.setLineWidth(1f);   //設(shè)置線條寬度
        lineDataSet.setCircleRadius(4f);//設(shè)置每個(gè)坐標(biāo)點(diǎn)的圓大小
        lineDataSet.setDrawCircleHole(false);//是否定制節(jié)點(diǎn)圓心的顏色,若為false,則節(jié)點(diǎn)為單一的同色點(diǎn),若為true則可以設(shè)置節(jié)點(diǎn)圓心的顏色
        lineDataSet.setValueTextSize(9f);   //設(shè)置 DataSets 數(shù)據(jù)對(duì)象包含的數(shù)據(jù)的值文本的大?。▎挝皇莇p)。
        //設(shè)置折線圖填充
        lineDataSet.setDrawFilled(false);    //Fill填充,可以將折線圖以下部分用顏色填滿
        lineDataSet.setFillAlpha(65);       ////設(shè)置填充區(qū)域透明度,默認(rèn)值為85
        lineDataSet.setFillColor(ColorTemplate.getHoloBlue());//設(shè)置填充顏色
        lineDataSet.setFormLineWidth(1f);
        lineDataSet.setFormSize(15.f);
        dataSets.add(lineDataSet);
    }
    LineData data = new LineData(dataSets);
    lineChart.setData(data);    //添加數(shù)據(jù)

}

  /**
 * 設(shè)置線條名字集合
 * @param count
 */
private void initChartNames(int count) {
    nameList = new ArrayList<>();
    for (int i = 0; i < count; i++) {
        int j = i+1;
        String name = "線條" + j;
        nameList.add(name);
    }
}

/**
 * 提前設(shè)置顏色集合
 */
private void initChartColors() {
    //顏色集合
    colours = new ArrayList<>();
    colours.add(Color.GREEN);
    colours.add(Color.BLUE);
    colours.add(Color.RED);
    colours.add(Color.CYAN);
    colours.add(Color.BLACK);
    colours.add(Color.GRAY);
}

由上代碼,相信看官老爺們不難看出,單條折線和多條折線的實(shí)現(xiàn)思路其實(shí)有異曲同工之妙。都是創(chuàng)建了一個(gè)ArrayList<ILineDataSet>集合,添加LineDataSet 對(duì)象并設(shè)置屬性。最后將此集合通過LineData的構(gòu)造方法,調(diào)用圖表對(duì)象的.setData()方法進(jìn)行添加的。

補(bǔ)充:

圖例,也就是這玩意


image.png

最好自己定義,寫個(gè)GirdView就可以了。還能自動(dòng)換行,美滋滋。官方的不多說,丑而且自動(dòng)換行有問題。

三.踩坑之處:

1.自定義X軸數(shù)據(jù)。
這里有一個(gè)不得不說的要點(diǎn),我們?cè)谧远xX軸數(shù)據(jù),創(chuàng)建自己的IAxisValueFormatter實(shí)現(xiàn)類時(shí),一定要注意提前設(shè)置 X軸的這個(gè)屬性:

//設(shè)置是否一個(gè)格子顯示一條數(shù)據(jù)
xAxis.setGranularity(1f);

如果不設(shè)置這個(gè)屬性,就會(huì)導(dǎo)致X軸數(shù)據(jù)重復(fù)并且錯(cuò)亂,原因是IAxisValueFormatter實(shí)現(xiàn)類的的方法getFormattedValue(float value, AxisBase axis)中的value返回錯(cuò)亂。

2.數(shù)據(jù)刷新。

如果你實(shí)現(xiàn)了自己的圖表控件,并且有多種類型的數(shù)據(jù)需要重復(fù)設(shè)置,需要刷新圖表控件時(shí),若有X軸經(jīng)常顯示錯(cuò)亂的問題,不妨多調(diào)用一次lineChart.setData(data);方法。

四.到此,就已經(jīng)實(shí)現(xiàn)了折線圖表的功能。隨手分享,喜歡的朋友可以關(guān)注微信公眾號(hào)MiHomes,后續(xù)會(huì)有更多更好的博客推送給您。


MiHomes.png

另:歡迎指出不足,會(huì)進(jìn)行更正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容