MPAndroidChart 曲线图LineChart使用部分示例
16lz
2021-01-26
前段是使用LineChart画图,有不少总结,毕竟要满足客户各种需求。有个是曲线动态变化,有一个是查询后查看数据。
这个开源库的GitHub地址:
https://github.com/PhilJay/MPAndroidChart
1,直接看两个封装的代码
import android.content.Context;import com.github.mikephil.charting.charts.LineChart;import com.github.mikephil.charting.components.AxisBase;import com.github.mikephil.charting.components.Description;import com.github.mikephil.charting.components.Legend;import com.github.mikephil.charting.components.XAxis;import com.github.mikephil.charting.components.YAxis;import com.github.mikephil.charting.data.Entry;import com.github.mikephil.charting.data.LineData;import com.github.mikephil.charting.data.LineDataSet;import com.github.mikephil.charting.formatter.DefaultValueFormatter;import com.github.mikephil.charting.formatter.IAxisValueFormatter;import com.gizwits.opensource.appkit.view.LineChartMarkView;import java.text.DecimalFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.List;/** * 动态参数变化 */public class DycLineChartManager { private LineChart lineChart; private YAxis leftAxis; private YAxis rightAxis; private XAxis xAxis; private LineData lineData; private LineDataSet lineDataSet; private SimpleDateFormat dfs = new SimpleDateFormat("HH:mm:ss");//设置日期格式 private List timeList = new ArrayList<>(); //存储x轴的时间 private int index = 0; private int indexX = 35; private List entries = new ArrayList<>(); private LineChartMarkView mv = null; protected int mDecimalDigits; protected DecimalFormat mFormat; //一条曲线 public DynamicLineChartManager(LineChart mLineChart, String name, String unit, int color, int mDecimalDigits, int digits) { this.lineChart = mLineChart; this.mDecimalDigits = mDecimalDigits; leftAxis = lineChart.getAxisLeft(); rightAxis = lineChart.getAxisRight(); xAxis = lineChart.getXAxis(); setup(digits); initLineChart(unit); initLineDataSet(name, color); } public void setup(int digits) { StringBuffer b = new StringBuffer(); for (int i = 0; i < digits; ++i) { if (i == 0) { b.append("."); } b.append("0"); } this.mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); } private long dateConvertMillionSec(String str) { long millionSeconds = 0; try { millionSeconds = new SimpleDateFormat("yyyyMMddHHmm").parse(str).getTime(); } catch (ParseException e) { e.printStackTrace(); } return millionSeconds; } /** * 初始化LineChar */ private void initLineChart(final String unit) { 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); Long time = System.currentTimeMillis(); String temp = ""; SimpleDateFormat now = new SimpleDateFormat("yyyyMMddHHmm"); String strNow = now.format(time); time = dateConvertMillionSec(strNow); timeList.add(dfs.format(time)); for (int i = 0; i < 360; i++) { //增加下一个5分钟的刻度 time = time + 1000 * 5; temp = dfs.format(time); timeList.add(temp); } xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { String temp = ""; int n = (int) value % timeList.size(); //修复了数组越界的异常 if (n > 0 && n < timeList.size()) { String tradeDate = timeList.get(n); temp = tradeDate.substring(tradeDate.length() - 2, tradeDate.length()); if (temp.equals("00")) { temp = tradeDate.substring(0, tradeDate.length() - 3); } else { temp = ""; } } return temp; } }); leftAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { String strTemp = mFormat.format(value) + " " + unit; return strTemp; } }); //X轴设置显示位置在底部 xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setGranularity(1f);// xAxis.setSpaceMax(1f); //保证Y轴从0开始,不然会上移一点 leftAxis.setAxisMinimum(0f); rightAxis.setAxisMinimum(0f); //将右边那条线隐藏 lineChart.getAxisRight().setEnabled(false); // 隐藏右边 的坐标轴 lineChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM); // 让x轴在下面 lineChart.getXAxis().setGridColor(0x00ffffff); lineChart.getXAxis().setDrawAxisLine(false); lineChart.getAxisRight().setDrawAxisLine(false); lineChart.invalidate(); } /** * 初始化折线(一条线) * * @param name * @param color */ private void initLineDataSet(String name, int color) { for (int i = 0; i < timeList.size(); i++) { Entry entry = new Entry(i, 0); entries.add(entry); } lineDataSet = new LineDataSet(entries, name); lineDataSet.setLineWidth(1.5f); lineDataSet.setCircleRadius(1.5f); lineDataSet.setColor(color); lineDataSet.setCircleColor(color); lineDataSet.setFillColor(color); lineDataSet.setHighLightColor(color); setDescription(""); lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT); //设置曲线填充 lineDataSet.setDrawFilled(true); lineDataSet.setValueTextSize(10f); //设置线型模式,设置CUBIC_BEZIER 时候,当数据跟密集,y轴数据很稀疏时候。线型更新时候会凸起 //所以换成LINEAR lineDataSet.setMode(LineDataSet.Mode.LINEAR); //添加一个空的 LineData lineData = new LineData(lineDataSet); //是否显示值 lineData.setDrawValues(false); //设置显示数据的多少位 很难找到这个方法 lineData.setValueFormatter(new DefaultValueFormatter(mDecimalDigits)); lineChart.setData(lineData);// lineChart.setScaleX(1f); //显示数量 xAxis.setLabelCount(360); //显示的时候是按照多大的比率缩放显示,1f表示不放大缩小 lineChart.zoom(1f, 1f, 0, 0); //缩放时候,能最大的显示范围 lineChart.setVisibleXRangeMaximum(36); lineChart.invalidate(); } /** * 动态添加数据(一条折线图) * * @param number */ public void addEntry(float number, int digits) { Entry entry = new Entry(index, number); entries.set(index, entry); lineDataSet.setValues(entries); lineData = new LineData(lineDataSet); //是否显示值 lineData.setDrawValues(false); //设置显示数据的多少位 很难找到这个方法 lineData.setValueFormatter(new DefaultValueFormatter(digits)); lineChart.setData(lineData); index++; //通知数据已经改变 lineData.notifyDataChanged(); lineChart.notifyDataSetChanged(); if (index > indexX) { indexX = indexX + 35; //移到某个位置 lineChart.moveViewToX(index - 2); } if (mv != null) { mv.refreshContent(entry, null); } lineChart.invalidate(); } /** * 设置Y轴值 */ public void setYAxis(float max, float min, int labelCount) { if (max < min) { return; } leftAxis.setAxisMaximum(max); leftAxis.setAxisMinimum(min); leftAxis.setLabelCount(labelCount, false); lineChart.invalidate(); } /** * 设置 可以显示X Y 轴自定义值的 MarkerView */ public void setMarkerView(Context context) { mv = new LineChartMarkView(context, xAxis.getValueFormatter(), timeList, mDecimalDigits); mv.setChartView(lineChart); lineChart.setMarker(mv); lineChart.invalidate(); } /** * 设置描述信息 * * @param str */ public void setDescription(String str) { Description description = new Description(); description.setText(str); description.setTextSize(14); lineChart.setDescription(description); lineChart.invalidate(); }}
import android.content.Context;import com.custom.net.HistoryData;import com.github.mikephil.charting.charts.LineChart;import com.github.mikephil.charting.components.AxisBase;import com.github.mikephil.charting.components.Description;import com.github.mikephil.charting.components.Legend;import com.github.mikephil.charting.components.LimitLine;import com.github.mikephil.charting.components.XAxis;import com.github.mikephil.charting.components.YAxis;import com.github.mikephil.charting.data.Entry;import com.github.mikephil.charting.data.LineData;import com.github.mikephil.charting.data.LineDataSet;import com.github.mikephil.charting.formatter.DefaultValueFormatter;import com.github.mikephil.charting.formatter.IAxisValueFormatter;import com.github.mikephil.charting.formatter.IValueFormatter;import com.github.mikephil.charting.highlight.Highlight;import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;import com.github.mikephil.charting.listener.OnChartValueSelectedListener;import com.github.mikephil.charting.utils.ViewPortHandler;import com.gizwits.opensource.appkit.view.LineChartMarkView;import java.lang.annotation.Target;import java.text.DecimalFormat;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.LinkedList;import java.util.List;import java.util.Locale;public class LineChartManager { private LineChart lineChart; private YAxis leftAxis; private YAxis rightAxis; private XAxis xAxis; private LineData lineData; private LineDataSet lineDataSet; List dataXList = new LinkedList<>(); protected int mDecimalDigits; protected DecimalFormat mFormat; //一条曲线 public ShowLineChartManager(LineChart mLineChart, String unit, int digits) { this.lineChart = mLineChart; leftAxis = lineChart.getAxisLeft(); rightAxis = lineChart.getAxisRight(); xAxis = lineChart.getXAxis(); setup(digits); initLineChart(unit); } public void setup(int digits) { StringBuffer b = new StringBuffer(); for (int i = 0; i < digits; ++i) { if (i == 0) { b.append("."); } b.append("0"); } this.mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); } /** * 初始化LineChar */ private void initLineChart(final String unit) { 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); //设置图表距离上下左右的距离 lineChart.setExtraOffsets(0, 0, 0, 10); //X轴设置显示位置在底部 xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setGranularity(1f); xAxis.setGridLineWidth(2f); leftAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { String strTemp = mFormat.format(value) + " " + unit; return strTemp; } }); //保证Y轴从0开始,不然会上移一点 leftAxis.setAxisMinimum(0f); rightAxis.setAxisMinimum(0f); //将右边那条线隐藏 lineChart.getAxisRight().setEnabled(false); // 隐藏右边 的坐标轴 lineChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM); // 让x轴在下面 lineChart.getXAxis().setGridColor(0x00ffffff); // 设置右边的label不可用 rightAxis.setDrawLabels(false); // 设置右边的线不可用 rightAxis.setDrawGridLines(false); // 设置右边的线不可用 rightAxis.setDrawAxisLine(false); } /** * 初始化折线(一条线) */ public void initLineDataSet(final List dataList, String name, int color, int digits) { float value = Collections.max(dataList); this.mDecimalDigits = digits; List entries = new ArrayList<>(); for (int i = 0; i < dataList.size(); i++) { /** * 在此可查看 Entry构造方法,可发现 可传入数值 Entry(float x, float y) * 也可传入Drawable, Entry(float x, float y, Drawable icon) 可在XY轴交点 设置Drawable图像展示 */ Entry entry = new Entry(i, dataList.get(i)); entries.add(entry); } // 每一个LineDataSet代表一条线 lineDataSet = new LineDataSet(entries, name); lineDataSet.setLineWidth(1.5f); lineDataSet.setCircleRadius(1.5f); lineDataSet.setColor(color); lineDataSet.setCircleColor(color); lineDataSet.setFillColor(color); lineDataSet.setHighLightColor(color); setDescription(""); lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT); //设置曲线填充 lineDataSet.setDrawFilled(true); lineDataSet.setValueTextSize(10f); lineDataSet.setMode(LineDataSet.Mode.LINEAR); //设置参数 lineData = new LineData(lineDataSet); //设置显示数据的多少位 很难找到这个方法 lineData.setValueFormatter(new DefaultValueFormatter(digits)); //是否显示值 lineData.setDrawValues(false); lineChart.setData(lineData); xAxis.setLabelCount(30); //显示的时候是按照多大的比率缩放显示,1f表示不放大缩小 lineChart.zoom(1f, 1f, 0, 0); lineChart.setScaleMinima(1f,1f); lineChart.setVisibleXRangeMaximum(30); //移到某个位置 lineChart.moveViewToX(lineData.getEntryCount()); lineChart.invalidate(); } /** * 设置Y轴值 */ public void setYAxis(float max, float min, int labelCount) { if (max < min) { return; } leftAxis.setAxisMaximum(max); leftAxis.setAxisMinimum(min); leftAxis.setLabelCount(labelCount, false); lineChart.invalidate(); } /** * 设置X轴值 */ public void setXAxis(final List dataList) { for (HistoryData data : dataList) { String tradeDate = data.getDatetime(); if (tradeDate.length() >= 10) { String temp = tradeDate.substring(tradeDate.length() - 2, tradeDate.length()); if (temp.equals("00")) { tradeDate = tradeDate.substring(0, 4) + "年" + tradeDate.substring(tradeDate.length() - 6, tradeDate.length() - 4) + "月" + tradeDate.substring(tradeDate.length() - 4, tradeDate.length() - 2) + "日"; } else { tradeDate = tradeDate.substring(0, 4) + "年" + tradeDate.substring(tradeDate.length() - 6, tradeDate.length() - 4) + "月" + tradeDate.substring(tradeDate.length() - 4, tradeDate.length() - 2) + "日" + temp.replaceFirst("^0*", "") + "时"; } dataXList.add(tradeDate); } } xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { String tradeDate = dataList.get((int) value).getDatetime(); if (tradeDate.length() >= 10) { String temp = tradeDate.substring(tradeDate.length() - 2, tradeDate.length()); if (temp.equals("00") || temp.equals("24")) { tradeDate = tradeDate.substring(tradeDate.length() - 6, tradeDate.length() - 4) + "-" + tradeDate.substring(tradeDate.length() - 4, tradeDate.length() - 2); } else { tradeDate = temp.replaceFirst("^0*", ""); switch (tradeDate) { case "3": case "6": case "9": case "12": case "15": case "18": case "21": break; default: tradeDate = ""; break; } } } return tradeDate; } }); lineChart.invalidate(); } /** * 设置 可以显示X Y 轴自定义值的 MarkerView */ public void setMarkerView(Context context) { LineChartMarkView mv = new LineChartMarkView(context, xAxis.getValueFormatter(), dataXList, mDecimalDigits); mv.setChartView(lineChart); lineChart.setMarker(mv); lineChart.invalidate(); } /** * 设置描述信息 * * @param str */ public void setDescription(String str) { Description description = new Description(); description.setText(str); description.setTextSize(14); lineChart.setDescription(description); lineChart.invalidate(); }}
里面涉及到很多小技巧。
还有一个弹出来显示的数值。
package com.gizwits.opensource.appkit.view;import android.annotation.SuppressLint;import android.content.Context;import android.text.TextUtils;import android.widget.TextView;import com.github.mikephil.charting.charts.Chart;import com.github.mikephil.charting.charts.LineChart;import com.github.mikephil.charting.components.MarkerView;import com.github.mikephil.charting.data.Entry;import com.github.mikephil.charting.data.LineData;import com.github.mikephil.charting.data.LineDataSet;import com.github.mikephil.charting.formatter.IAxisValueFormatter;import com.github.mikephil.charting.highlight.Highlight;import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;import com.github.mikephil.charting.utils.MPPointF;import com.gizwits.opensource.appkit.R;import java.text.DecimalFormat;import java.util.EventListener;import java.util.LinkedList;import java.util.List;/** * Created by xhu_ww on 2018/6/1. * description: */public class LineChartMarkView extends MarkerView { private TextView tvDate; private TextView tvValue0; private IAxisValueFormatter xAxisValueFormatter; List dataXList = new LinkedList<>(); protected DecimalFormat mFormat; protected int mDecimalDigits; public LineChartMarkView(Context context, IAxisValueFormatter xAxisValueFormatter, List dataXList, int digits) { super(context, R.layout.layout_markview); this.xAxisValueFormatter = xAxisValueFormatter; this.dataXList = dataXList; this.mDecimalDigits = digits; setup(mDecimalDigits); tvDate = (TextView) findViewById(R.id.tv_date); tvValue0 = (TextView) findViewById(R.id.tv_value0); } public void setup(int digits) { this.mDecimalDigits = digits; StringBuffer b = new StringBuffer(); for(int i = 0; i < digits; ++i) { if(i == 0) { b.append("."); } b.append("0"); } this.mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); } @SuppressLint("SetTextI18n") @Override public void refreshContent(Entry e, Highlight highlight) { Chart chart = getChartView(); if (chart instanceof LineChart) { LineData lineData = ((LineChart) chart).getLineData(); //获取到图表中的所有曲线 List dataSetList = lineData.getDataSets(); for (int i = 0; i < dataSetList.size(); i++) { LineDataSet dataSet = (LineDataSet) dataSetList.get(i); //获取到曲线的所有在Y轴的数据集合,根据当前X轴的位置 来获取对应的Y轴值 float y = dataSet.getValues().get((int) e.getX()).getY(); if (i == 0) { tvValue0.setText(dataSet.getLabel() + ":" + mFormat.format(y)); } }// String temp = xAxisValueFormatter.getFormattedValue(e.getX(), null); //获取全部刻度,包括不显示的刻度 String temp = dataXList.get((int) e.getX()); if (!TextUtils.isEmpty(temp)) { tvDate.setText(temp); } } super.refreshContent(e, highlight); } @Override public MPPointF getOffset() { return new MPPointF(-(getWidth() / 2), -getHeight()); }}
更多相关文章
- 一句话锁定MySQL数据占用元凶
- ubuntu android 编译环境设置
- [zz]Android(安卓)Button背景图片
- Android(安卓)- 向服务器发送数据(GET).
- Android(安卓)5.X的新特性实例
- Android百度地图开发(二)地图覆盖物
- Android(安卓)代码控制手机数据网络的开关(5.0以上)
- Android18_Content Provider
- activity跳转黑屏但不透明桌面问题