Android圖表控制元件MPAndroidChart——曲線圖LineChart(多條曲線)動態新增資料
阿新 • • 發佈:2019-02-15
發現最新的MPAndroidChart和以前版本的使用有一些差距,就寫下了現在新版的使用方法
相關文章:
一.效果圖
一條曲線動態新增資料(X軸為當前時間)
多條曲線線動態新增資料(X軸為當前時間)
二.實現效果
1.X軸為當前時間,只需要Y軸資料即可
2.X軸的值為字串,而Entry的構造方法引數全為float public Entry(float x, float y) 所以需要另外定義X軸的值
簡要程式碼
動態新增值Entry
Entry entry = new Entry(lineDataSet.getEntryCount(), number); lineData.addEntry(entry,0); //通知資料已經改變 lineData.notifyDataChanged(); lineChart.notifyDataSetChanged(); //設定在曲線圖中顯示的最大數量 lineChart.setVisibleXRangeMaximum(10); //移到某個位置 lineChart.moveViewToX(lineData.getEntryCount() - 5);
X軸值的設定
我並沒有找到直接設定X軸為當前時間的方法,
而是新建一個字串集合,選擇在每次新增Entry的時候將當前時間新增進集合,然後設定X軸的值
private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//設定日期格式private List<String> timeList = new ArrayList<>(); //儲存x軸的時間
xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return timeList.get((int) value % timeList.size()); } });
三.詳細程式碼(一個管理類)
public class DynamicLineChartManager { privateLineChart lineChart; private YAxis leftAxis; private YAxis rightAxis; private XAxis xAxis; private LineData lineData; private LineDataSet lineDataSet; private List<ILineDataSet> lineDataSets = new ArrayList<>(); private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//設定日期格式private List<String> timeList = new ArrayList<>(); //儲存x軸的時間 //一條曲線 public DynamicLineChartManager(LineChart mLineChart, String name, int color) { this.lineChart = mLineChart; leftAxis = lineChart.getAxisLeft(); rightAxis = lineChart.getAxisRight(); xAxis = lineChart.getXAxis(); initLineChart(); initLineDataSet(name, color); } //多條曲線 public DynamicLineChartManager(LineChart mLineChart, List<String> names, List<Integer> colors) { this.lineChart = mLineChart; leftAxis = lineChart.getAxisLeft(); rightAxis = lineChart.getAxisRight(); xAxis = lineChart.getXAxis(); initLineChart(); initLineDataSet(names, colors); } /** * 初始化LineChar */ private void initLineChart() { lineChart.setDrawGridBackground(false); //顯示邊界 lineChart.setDrawBorders(true); //折線圖例 標籤 設定 Legend legend = lineChart.getLegend(); legend.setForm(Legend.LegendForm.LINE); legend.setTextSize(11f); //顯示位置 legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); legend.setOrientation(Legend.LegendOrientation.HORIZONTAL); legend.setDrawInside(false); //X軸設定顯示位置在底部 xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setGranularity(1f); xAxis.setLabelCount(10); xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return timeList.get((int) value % timeList.size()); } }); //保證Y軸從0開始,不然會上移一點 leftAxis.setAxisMinimum(0f); rightAxis.setAxisMinimum(0f); } /** * 初始化折線(一條線) * * @param name * @param color */ private void initLineDataSet(String name, int color) { lineDataSet = new LineDataSet(null, name); lineDataSet.setLineWidth(1.5f); lineDataSet.setCircleRadius(1.5f); lineDataSet.setColor(color); lineDataSet.setCircleColor(color); lineDataSet.setHighLightColor(color); //設定曲線填充 lineDataSet.setDrawFilled(true); lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT); lineDataSet.setValueTextSize(10f); lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); //新增一個空的 LineData lineData = new LineData(); lineChart.setData(lineData); lineChart.invalidate(); } /** * 初始化折線(多條線) * * @param names * @param colors */ private void initLineDataSet(List<String> names, List<Integer> colors) { for (int i = 0; i < names.size(); i++) { lineDataSet = new LineDataSet(null, names.get(i)); lineDataSet.setColor(colors.get(i)); lineDataSet.setLineWidth(1.5f); lineDataSet.setCircleRadius(1.5f); lineDataSet.setColor(colors.get(i)); lineDataSet.setDrawFilled(true); lineDataSet.setCircleColor(colors.get(i)); lineDataSet.setHighLightColor(colors.get(i)); lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT); lineDataSet.setValueTextSize(10f); lineDataSets.add(lineDataSet); } //新增一個空的 LineData lineData = new LineData(); lineChart.setData(lineData); lineChart.invalidate(); } /** * 動態新增資料(一條折線圖) * * @param number */ public void addEntry(int number) { //最開始的時候才新增 lineDataSet(一個lineDataSet 代表一條線) if (lineDataSet.getEntryCount() == 0) { lineData.addDataSet(lineDataSet); } lineChart.setData(lineData); //避免集合資料過多,及時清空(做這樣的處理,並不知道有沒有用,但還是這樣做了) if (timeList.size() > 11) { timeList.clear(); } timeList.add(df.format(System.currentTimeMillis())); Entry entry = new Entry(lineDataSet.getEntryCount(), number); lineData.addEntry(entry, 0); //通知資料已經改變 lineData.notifyDataChanged(); lineChart.notifyDataSetChanged(); //設定在曲線圖中顯示的最大數量 lineChart.setVisibleXRangeMaximum(10); //移到某個位置 lineChart.moveViewToX(lineData.getEntryCount() - 5); } /** * 動態新增資料(多條折線圖) * * @param numbers */ public void addEntry(List<Integer> numbers) { if (lineDataSets.get(0).getEntryCount() == 0) { lineData = new LineData(lineDataSets); lineChart.setData(lineData); } if (timeList.size() > 11) { timeList.clear(); } timeList.add(df.format(System.currentTimeMillis())); for (int i = 0; i < numbers.size(); i++) { Entry entry = new Entry(lineDataSet.getEntryCount(), numbers.get(i)); lineData.addEntry(entry, i); lineData.notifyDataChanged(); lineChart.notifyDataSetChanged(); lineChart.setVisibleXRangeMaximum(6); lineChart.moveViewToX(lineData.getEntryCount() - 5); } } /** * 設定Y軸值 * * @param max * @param min * @param labelCount */ public void setYAxis(float max, float min, int labelCount) { if (max < min) { return; } leftAxis.setAxisMaximum(max); leftAxis.setAxisMinimum(min); leftAxis.setLabelCount(labelCount, false); rightAxis.setAxisMaximum(max); rightAxis.setAxisMinimum(min); rightAxis.setLabelCount(labelCount, false); lineChart.invalidate(); } /** * 設定高限制線 * * @param high * @param name */ public void setHightLimitLine(float high, String name, int color) { if (name == null) { name = "高限制線"; } LimitLine hightLimit = new LimitLine(high, name); hightLimit.setLineWidth(4f); hightLimit.setTextSize(10f); hightLimit.setLineColor(color); hightLimit.setTextColor(color); leftAxis.addLimitLine(hightLimit); lineChart.invalidate(); } /** * 設定低限制線 * * @param low * @param name */ public void setLowLimitLine(int low, String name) { if (name == null) { name = "低限制線"; } LimitLine hightLimit = new LimitLine(low, name); hightLimit.setLineWidth(4f); hightLimit.setTextSize(10f); leftAxis.addLimitLine(hightLimit); lineChart.invalidate(); } /** * 設定描述資訊 * * @param str */ public void setDescription(String str) { Description description = new Description(); description.setText(str); lineChart.setDescription(description); lineChart.invalidate(); } }
XML佈局
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.github.mikephil.charting.charts.LineChart android:id="@+id/dynamic_chart1" android:layout_width="match_parent" android:layout_height="380dp"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="addEntry" android:text="隨機資料" /> <com.github.mikephil.charting.charts.LineChart android:id="@+id/dynamic_chart2" android:layout_width="match_parent" android:layout_height="380dp"/> </LinearLayout> </ScrollView>
Activity中的程式碼
public class DynamicLineChartActivity extends AppCompatActivity { private DynamicLineChartManager dynamicLineChartManager1; private DynamicLineChartManager dynamicLineChartManager2; private List<Integer> list = new ArrayList<>(); //資料集合 private List<String> names = new ArrayList<>(); //折線名字集合 private List<Integer> colour = new ArrayList<>();//折線顏色集合 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_dynamic_linechart); LineChart mChart1 = (LineChart) findViewById(R.id.dynamic_chart1); LineChart mChart2 = (LineChart) findViewById(R.id.dynamic_chart2); //折線名字 names.add("溫度"); names.add("壓強"); names.add("其他"); //折線顏色 colour.add(Color.CYAN); colour.add(Color.GREEN); colour.add(Color.BLUE); dynamicLineChartManager1 = new DynamicLineChartManager(mChart1, names.get(0), colour.get(0)); dynamicLineChartManager2 = new DynamicLineChartManager(mChart2, names, colour); dynamicLineChartManager1.setYAxis(100, 0, 10); dynamicLineChartManager2.setYAxis(100, 0, 10); //死迴圈新增資料 new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { list.add((int) (Math.random() * 50) + 10); list.add((int) (Math.random() * 80) + 10); list.add((int) (Math.random() * 100)); dynamicLineChartManager2.addEntry(list); list.clear(); } }); } } }).start(); } //按鈕點選新增資料 public void addEntry(View view) { dynamicLineChartManager1.addEntry((int) (Math.random() * 100)); } }
四.使用中遇到的一些問題
1.X軸新增字串,或者設定顯示格式
xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return timeList.get((int) value % timeList.size()); } });
2.動態新增資料資料時,曲線不自動往左邊移動,而是擠在一堆
//設定在曲線圖中顯示的最大數量 lineChart.setVisibleXRangeMaximum(10); //移到某個位置 lineChart.moveViewToX(lineData.getEntryCount() - 5);