MpAndroidChart

您所在的位置:网站首页 折线图的使用范围 MpAndroidChart

MpAndroidChart

2023-11-19 15:27| 来源: 网络整理| 查看: 265

目录

零、简介

一、MpAndroidChart的基本使用

1.依赖:project的build.gradle 中添加

2.app的build.gradle 中添加

3.举例

4.常用API

二、MpAndroidChart-LineChart的基本使用配置

1.XAxis(X轴)

2.YAxis(Y轴)

3.Legend(图例:即上图所示的曲线图下面的 温度)

4.Description(描述)

5.MarkerView

6.折线图的线条设置

三、LineChart实现动态添加曲线,以及多曲线动态添加数据

1. 在xml中添加基本控件

2.初始化基本属性,控件

3. 初始化折线:initLineChart()

4. 设置图标基本属性:setChartBasicAttr()

5. 设置XY轴:setXYAxis()

6.初始化LineDataSet(一条曲线):initLineDataSet()

7.动态创建并添加一个线条:createLine()

8. 初始化项目中的三条折线:initLine()

9. 设置图例:createLegend()

10. 设置MarkerView: setMarkerView()

11.动态添加数据点:addEntry()

12.自定义Handler:DemoHandler

13. 点击事件:onClick()

14.最后一步,回收:onDestory

四、全部Java代码

零、简介

本文主要介绍MpAndroidChart中的折线图-LineChart的基本使用,包含动态添加点,动态添加线,以及曲线的隐藏与显示等等。

话不多说,先上图:

             

 

GitHub地址:https://github.com/PhilJay/MPAndroidChart

文档地址:https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.2/javadoc

一、MpAndroidChart的基本使用 1.依赖:project的build.gradle 中添加 allprojects { repositories { jcenter() maven { url "https://jitpack.io" } } } 2.app的build.gradle 中添加 implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha' 3.举例

3.1 xml中示例

3.2 java代码示例

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LineChart mLineChart = (LineChart) findViewById(R.id.lineChart); //显示边界 mLineChart.setDrawBorders(true); //设置数据 List entries = new ArrayList(); for (int i = 0; i < 10; i++) { entries.add(new Entry(i, (float) (Math.random()) * 80)); } //一个LineDataSet就是一条线 LineDataSet lineDataSet = new LineDataSet(entries, "温度"); LineData data = new LineData(lineDataSet); mLineChart.setData(data); }

3.3 效果图:

4.常用API setDescription(String desc) : 设置表格的描述setDescriptionTypeface(Typeface t) :自定义表格中显示的字体setDrawYValues(boolean enabled) : 设置是否显示y轴的值的数据setValuePaintColor(int color) :设置表格中y轴的值的颜色,但是必须设置setDrawYValues(true)setValueTypeface(Typeface t):设置字体setValueFormatter(DecimalFormat format) : 设置显示的格式setPaint(Paint p, int which) : 自定义笔刷 public ChartData getDataCurrent() :返回ChartData对象当前显示的图表。它包含了所有信息的显示值最小和最大值等public float getYChartMin() : 返回当前最小值public float getYChartMax() : 返回当前最大值public float getAverage() : 返回所有值的平均值。public float getAverage(int type) : 返回平均值public PointF getCenter() : 返回中间点public Paint getPaint(int which) : 得到笔刷 setTouchEnabled(boolean enabled) : 设置是否可以触摸,如为false,则不能拖动,缩放等setDragScaleEnabled(boolean enabled) : 设置是否可以拖拽,缩放setOnChartValueSelectedListener(OnChartValueSelectedListener l) : 设置表格上的点,被点击的时候,的回调函数setHighlightEnabled(boolean enabled) : 设置点击value的时候,是否高亮显示public void highlightValues(Highlight[] highs) : 设置高亮显示 saveToGallery(String title) : 保存图表到图库中saveToPath(String title, String pathOnSD) : 保存.setScaleMinima(float x, float y) : 设置最小的缩放centerViewPort(int xIndex, float val) : 设置视口fitScreen() : 适应屏幕

动画:

所有的图表类型都支持下面三种动画,分别是x方向,y方向,xy方向。

animateX(int durationMillis) : x轴方向animateY(int durationMillis) : y轴方向animateXY(int xDuration, int yDuration) : xy轴方向 二、MpAndroidChart-LineChart的基本使用配置

使用MpAndroidchart前首先要明白几个概念,以免在编码时混淆概念

LineChart // 折线表,存线集合,与xml中的控件绑定实力化 LineData // 线集合,所有折线以数组的形式存到此集合中 LineDataSet // 点集合,即一条折线 Entry // 某条折线上的一个点 XAxis // X轴 YAxis // Y轴,Y轴分左右,通过lineChart的getAxisLeft()、getAxisRight()得到 Legend // 图例,即标识哪一条曲线,如用红色标识电流折线,蓝色标识电压折线 LimitLine // 限制线 Description // 描述 List list = new ArrayList(); // 存放数据的list列表 List entrys = new ArrayList(); // 存放折线需要的点的列表 LineDataSet mStepTimeDataSet = new LineDataSet(entrys, "步时间"); // LineDataSet:点集合,即一条线

图解

1.XAxis(X轴)

设置x轴需要注意一下几个点:

设置x轴的坐标之间的最小间隔,如xAxis.setGranularity(1f),即间隔为1、设置x轴的最大/小值,xAxis.setAxisMinimum(0f),xAxis.setAxisMaximum(20f),则x轴的范围是0-20设置x轴的刻度数量,xAxis.setLabelCount(10, true),即x轴有10个刻度线,此时一个刻度表示2,如果是将10改为40,由于之前设置了坐标之间的间隔,所以x轴一个刻度会表示1,而不是0.5.设置当前页面显示几个刻度,mLineChart.setVisibleXRangeMaximum(6),// 设置当前图表中最多在x轴坐标线上显示的刻度线总量为6 1.得到X轴: XAxis xAxis = mLineChart.getXAxis(); 2.设置X轴的位置(默认在上方): xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);//值:BOTTOM,BOTH_SIDED,BOTTOM_INSIDE,TOP,TOP_INSIDE 3.设置X轴坐标之间的最小间隔(因为此图有缩放功能,X轴,Y轴可设置可缩放) xAxis.setGranularity(1f); 4.设置X轴的刻度数量 xAxis.setLabelCount(12, true); 5.设置X轴的值(最小值、最大值、然后会根据设置的刻度数量自动分配刻度显示) xAxis.setAxisMinimum(0f); xAxis.setAxisMaximum(20f); 6.设置当前图表中最多在x轴坐标线上显示刻度线的总量 mLineChart.setVisibleXRangeMaximum(6);// 设置当前图表中最多在x轴坐标线上显示的刻度线总量为6 7.设置X轴值为字符串(如上右图) xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return mList.get((int) value); //mList为存有月份的String集合 } }); 想要显示完整的12个月份,要与(x,y)坐标对应数量应该为12 for (int i = 0; i < 12; i++) { entries.add(new Entry(i, (float) (Math.random()) * 80)); //Entry(float x, float y) } 还有设置线条颜色、字体颜色、等等,可查看详细的文档。 8.取消曲线显示的值为整数 与设置自定义X轴类似,设置曲线显示值为整数,可在设置曲线LineDataSet 时,修改值的类型 lineDataSet.setValueFormatter(new IValueFormatter() { @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { int IValue = (int) value; return String.valueOf(IValue); } }); 2.YAxis(Y轴)

Y轴和X轴类似,不过Y轴分左右,这里只介绍几个不同的地方

1.得到Y轴 YAxis leftYAxis = mLineChart.getAxisLeft(); YAxis rightYAxis = mLineChart.getAxisRight(); 2.设置某一个Y轴是否显示 rightYAxis.setEnabled(false); //右侧Y轴不显示 3.限制线LimitLine(如上右图) LimitLine limitLine = new LimitLine(95,"高限制性"); //得到限制线 limitLine.setLineWidth(4f); //宽度 limitLine.setTextSize(10f); limitLine.setTextColor(Color.RED); //颜色 limitLine.setLineColor(Color.BLUE); rightYAxis.addLimitLine(limitLine); //Y轴添加限制线 4.X轴和Y轴类似,都具有相同的属性方法 rightYAxis.setAxisMinimum(0f); rightYAxis.setAxisMaximum(100f); rightYAxis.setGranularity(1f); rightYAxis.setLabelCount(11,false); rightYAxis.setTextColor(Color.BLUE); //文字颜色 rightYAxis.setGridColor(Color.RED); //网格线颜色 rightYAxis.setAxisLineColor(Color.GREEN); //Y轴颜色 以及格式化Y轴的值 leftYAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return (int) value + "%"; } }); 3.Legend(图例:即上图所示的曲线图下面的 温度) 1.得到Lengend Legend legend = mLineChart.getLegend(); 2.设置Lengend位置 legend.setTextColor(Color.CYAN); //设置Legend 文本颜色 legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); legend.setOrientation(Legend.LegendOrientation.HORIZONTAL); 3.设置标签是否换行(当多条标签时 需要换行显示、如上右图) true:可换行。false:不换行 legend.setWordWrapEnabled(true); 4.隐藏Lengend legend.setEnabled(false); 4.Description(描述) 1.隐藏描述 Description description = new Description(); description.setEnabled(false); mLineChart.setDescription(description); 2.设置描述内容 Description description = new Description(); description.setText("X轴描述"); description.setTextColor(Color.RED); mLineChart.setDescription(description); 5.MarkerView

MarkerView可自定义,用于点击图标值时显示想要的内容

1.自定义MarkerView public class MyMarkerView extends MarkerView { private TextView tvContent; private DecimalFormat format = new DecimalFormat("##0"); public MyMarkerView(Context context) { super(context, R.layout.layout_markerview); tvContent = (TextView) findViewById(R.id.tvContent); } @Override public void refreshContent(Entry e, Highlight highlight) { tvContent.setText(format.format(e.getY())); super.refreshContent(e, highlight); } @Override public MPPointF getOffset() { return new MPPointF(-(getWidth() / 2), -getHeight() - 10); } } 2.设置显示MarkerView MyMarkerView mv = new MyMarkerView(this); mLineChart.setMarkerView(mv); 6.折线图的线条设置 LineDataSet lineDataSet = new LineDataSet(entries, "温度");//一个LineDataSet就是一条线 lineDataSet.setDrawCircleHole(false);//设置曲线值的圆点是实心还是空心 lineDataSet.setValueTextSize(9f);//设置显示值的字体大小 lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);//线模式为圆滑曲线(默认折线) 三、LineChart实现动态添加曲线,以及多曲线动态添加数据

接下来我们实现一个LineChart图表,它包含动态添加曲线,以及多曲线动态添加数据,

下面是代码逻辑:

默认添加三条折线,但是这三条曲线中暂时不添加点,后面我们动态添加有个Handler用于发从动态添加点的消息,延时一秒发一次有两个Button,一个控制开始添加点,一个控制暂停添加点还有三个CheckBox,对应三条折线,那个选中便显示哪条曲线

效果图:

 

1. 在xml中添加基本控件 2.初始化基本属性,控件

首先声明了Handler所需要的消息,折线编号,基本控件,以及LineChart所需要的对象。

之后 封装了Activity的启动方式,以及随机产生Y值的方法。

然后在onCreate方法中对控件初始化

public class LineChartDemo extends AppCompatActivity implements View.OnClickListener { public static final int MSG_START = 1; // handler消息,开始添加点 // 折线编号 public static final int LINE_NUMBER_1 = 0; public static final int LINE_NUMBER_2 = 1; public static final int LINE_NUMBER_3 = 2; /** * 功能:启动方式 */ public static void startActivity(Context context) { context.startActivity(new Intent(context, LineChartDemo.class)); } private DemoHandler mDemoHandler; // 自定义Handler private Random mRandom = new Random(); // 随机产生点 private DecimalFormat mDecimalFormat = new DecimalFormat("#.00"); // 格式化浮点数位两位小数 Button mBtnStart; // 开始添加点 Button mBtnPause; // 暂停添加点 CheckBox mCheckBox1; CheckBox mCheckBox2; CheckBox mCheckBox3; List mCheckBoxList = new ArrayList(); LineChart mLineChart; // 折线表,存线集合 LineData mLineData; // 线集合,所有折现以数组的形式存到此集合中 XAxis mXAxis; //X轴 YAxis mLeftYAxis; //左侧Y轴 YAxis mRightYAxis; //右侧Y轴 Legend mLegend; //图例 LimitLine mLimitline; //限制线 // Y值数据链表 List mList1 = new ArrayList(); List mList2 = new ArrayList(); List mList3 = new ArrayList(); // Chart需要的点数据链表 List mEntries1 = new ArrayList(); List mEntries2 = new ArrayList(); List mEntries3 = new ArrayList(); // LineDataSet:点集合,即一条线 LineDataSet mLineDataSet1 = new LineDataSet(mEntries1, "折线1"); LineDataSet mLineDataSet2 = new LineDataSet(mEntries2, "折线2"); LineDataSet mLineDataSet3 = new LineDataSet(mEntries3, "折线3"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.demo_activity_line_chart); mDemoHandler = new DemoHandler(this); initView(); } /** * 功能:产生随机数(小数点两位) */ public Float getRandom(Float seed) { return Float.valueOf(mDecimalFormat.format(mRandom.nextFloat() * seed)); } /** * 功能:初始化基本控件,button,checkbox */ public void initView() { mBtnStart = findViewById(R.id.demo_start); mBtnPause = findViewById(R.id.demo_pause); mCheckBox1 = findViewById(R.id.demo_checkbox1); mCheckBox2 = findViewById(R.id.demo_checkbox2); mCheckBox3 = findViewById(R.id.demo_checkbox3); mCheckBoxList.add(mCheckBox1); mCheckBoxList.add(mCheckBox2); mCheckBoxList.add(mCheckBox3); mBtnStart.setOnClickListener(this); mBtnPause.setOnClickListener(this); mCheckBox1.setOnClickListener(this); mCheckBox2.setOnClickListener(this); mCheckBox3.setOnClickListener(this); } } 3. 初始化折线:initLineChart() @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.demo_activity_line_chart); mDemoHandler = new DemoHandler(this); initView(); // 初始化控件 initLineChart(); // 初始化折线图 }

initLineChart()方法:

/** * 功能:初始化LineChart */ public void initLineChart() { mLineChart = findViewById(R.id.demo_linechart); mXAxis = mLineChart.getXAxis(); // 得到x轴 mLeftYAxis = mLineChart.getAxisLeft(); // 得到侧Y轴 mRightYAxis = mLineChart.getAxisRight(); // 得到右侧Y轴 mLegend = mLineChart.getLegend(); // 得到图例 mLineData = new LineData(); mLineChart.setData(mLineData); // 设置图标基本属性 setChartBasicAttr(mLineChart); // 设置XY轴 setXYAxis(mLineChart, mXAxis, mLeftYAxis, mRightYAxis); // 添加线条 initLine(); // 设置图例 createLegend(mLegend); // 设置MarkerView setMarkerView(mLineChart); } 4. 设置图标基本属性:setChartBasicAttr() /** * 功能:设置图标的基本属性 */ void setChartBasicAttr(LineChart lineChart) { /***图表设置***/ lineChart.setDrawGridBackground(false); //是否展示网格线 lineChart.setDrawBorders(true); //是否显示边界 lineChart.setDragEnabled(true); //是否可以拖动 lineChart.setScaleEnabled(true); // 是否可以缩放 lineChart.setTouchEnabled(true); //是否有触摸事件 //设置XY轴动画效果 //lineChart.animateY(2500); lineChart.animateX(1500); } 5. 设置XY轴:setXYAxis() /** * 功能:设置XY轴 */ void setXYAxis(LineChart lineChart, XAxis xAxis, YAxis leftYAxis, YAxis rightYAxis) { /***XY轴的设置***/ xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //X轴设置显示位置在底部 xAxis.setAxisMinimum(0f); // 设置X轴的最小值 xAxis.setAxisMaximum(20); // 设置X轴的最大值 xAxis.setLabelCount(20, false); // 设置X轴的刻度数量,第二个参数表示是否平均分配 xAxis.setGranularity(1f); // 设置X轴坐标之间的最小间隔 lineChart.setVisibleXRangeMaximum(5);// 当前统计图表中最多在x轴坐标线上显示的总量 //保证Y轴从0开始,不然会上移一点 leftYAxis.setAxisMinimum(0f); rightYAxis.setAxisMinimum(0f); leftYAxis.setAxisMaximum(100f); rightYAxis.setAxisMaximum(100f); leftYAxis.setGranularity(1f); rightYAxis.setGranularity(1f); leftYAxis.setLabelCount(20); lineChart.setVisibleYRangeMaximum(30, YAxis.AxisDependency.LEFT);// 当前统计图表中最多在Y轴坐标线上显示的总量 lineChart.setVisibleYRangeMaximum(30, YAxis.AxisDependency.RIGHT);// 当前统计图表中最多在Y轴坐标线上显示的总量 leftYAxis.setEnabled(false); // leftYAxis.setCenterAxisLabels(true);// 将轴标记居中 // leftYAxis.setDrawZeroLine(true); // 原点处绘制 一条线 // leftYAxis.setZeroLineColor(Color.RED); // leftYAxis.setZeroLineWidth(1f); } 6.初始化LineDataSet(一条曲线):initLineDataSet()

此方法被在创建一个线条时调用,为曲线初始化做好准备

/** * 曲线初始化设置,一个LineDataSet 代表一条曲线 * * @param lineDataSet 线条 * @param color 线条颜色 * @param mode */ private void initLineDataSet(LineDataSet lineDataSet, int color, LineDataSet.Mode mode) { lineDataSet.setColor(color); // 设置曲线颜色 lineDataSet.setCircleColor(color); // 设置数据点圆形的颜色 lineDataSet.setDrawCircleHole(false);// 设置曲线值的圆点是否是空心 lineDataSet.setLineWidth(1f); // 设置折线宽度 lineDataSet.setCircleRadius(3f); // 设置折现点圆点半径 lineDataSet.setValueTextSize(10f); lineDataSet.setDrawFilled(true); //设置折线图填充 lineDataSet.setFormLineWidth(1f); lineDataSet.setFormSize(15.f); if (mode == null) { //设置曲线展示为圆滑曲线(如果不设置则默认折线) lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); } else { lineDataSet.setMode(mode); } } 7.动态创建并添加一个线条:createLine()

根据传进来的dataList,生成点Entry,之后根据生成的点更新折线图即可

/** * 功能:动态创建一条曲线 */ private void createLine(List dataList, List entries, LineDataSet lineDataSet, int color, LineData lineData, LineChart lineChart) { 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));// Entry(x,y) entries.add(entry); } // 初始化线条 initLineDataSet(lineDataSet, color, LineDataSet.Mode.CUBIC_BEZIER); if (lineData == null) { lineData = new LineData(); lineData.addDataSet(lineDataSet); lineChart.setData(lineData); } else { lineChart.getLineData().addDataSet(lineDataSet); } lineChart.invalidate(); } 8. 初始化项目中的三条折线:initLine()

首先创建三条折线,之后设置三条折线隐藏,最后根据配置默认显示第一条折线

/** * 功能:对图表中的曲线初始化,添加三条,并且默认显示第一条 */ void initLine() { createLine(mList1, mEntries1, mLineDataSet1, LColor.Colors.RED.getColor(), mLineData, mLineChart); createLine(mList2, mEntries2, mLineDataSet2, LColor.Colors.ORANGE.getColor(), mLineData, mLineChart); createLine(mList3, mEntries3, mLineDataSet3, LColor.Colors.YELLOW.getColor(), mLineData, mLineChart); // mLineData.getDataSetCount() 总线条数 // mLineData.getEntryCount() 总点数 // mLineData.getDataSetByIndex(index).getEntryCount() 索引index处折线的总点数 // 每条曲线添加到mLineData后,从索引0处开始排列 for (int i = 0; i < mLineData.getDataSetCount(); i++) { mLineChart.getLineData().getDataSets().get(i).setVisible(false); // } showLine(LINE_NUMBER_1); } 9. 设置图例:createLegend() /** * 功能:创建图例 */ private void createLegend(Legend legend) { /***折线图例 标签 设置***/ //设置显示类型,LINE CIRCLE SQUARE EMPTY 等等 多种方式,查看LegendForm 即可 legend.setForm(Legend.LegendForm.CIRCLE); legend.setTextSize(12f); //显示位置 左下方 legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); legend.setOrientation(Legend.LegendOrientation.HORIZONTAL); //是否绘制在图表里面 legend.setDrawInside(false); legend.setEnabled(true); } 10. 设置MarkerView: setMarkerView() /** * 设置 可以显示X Y 轴自定义值的 MarkerView */ public void setMarkerView(LineChart lineChart) { LineChartMarkViewDemo mv = new LineChartMarkViewDemo(this); mv.setChartView(lineChart); lineChart.setMarker(mv); lineChart.invalidate(); }

LineChartMarkViewDemo是自定义的,这个很简单,一般是自定义XML,之后继承MarkView即可。

xml:

java

public class LineChartMarkViewDemo extends MarkerView { DecimalFormat df = new DecimalFormat(".00"); private TextView mXValueTv; private TextView mYValueTv; public LineChartMarkViewDemo(Context context) { super(context, R.layout.layout_markview); mXValueTv = findViewById(R.id.xValues_tv); mYValueTv = findViewById(R.id.yValue_tv); } @SuppressLint("SetTextI18n") @Override public void refreshContent(Entry e, Highlight highlight) { //展示自定义X轴值 后的X轴内容 mXValueTv.setText("X = " + df.format(e.getX())); mYValueTv.setText("Y = " + df.format(e.getY())); super.refreshContent(e, highlight); } @Override public MPPointF getOffset() { return new MPPointF(-(getWidth() / 2), -getHeight()); } } 11.动态添加数据点:addEntry() /** * 动态添加数据 * 在一个LineChart中存放的折线,其实是以索引从0开始编号的 * * @param yValues y值 */ public void addEntry(LineData lineData, LineChart lineChart, float yValues, int index) { // 通过索引得到一条折线,之后得到折线上当前点的数量 int xCount = lineData.getDataSetByIndex(index).getEntryCount(); Entry entry = new Entry(xCount, yValues); // 创建一个点 lineData.addEntry(entry, index); // 将entry添加到指定索引处的折线中 //通知数据已经改变 lineData.notifyDataChanged(); lineChart.notifyDataSetChanged(); //把yValues移到指定索引的位置 lineChart.moveViewToAnimated(xCount - 4, yValues, YAxis.AxisDependency.LEFT, 1000);// TODO: 2019/5/4 内存泄漏,异步 待修复 lineChart.invalidate(); } /** * 功能:第1条折线添加一个点 */ public void addLine1Data(float yValues) { addEntry(mLineData, mLineChart, yValues, LINE_NUMBER_1); } /** * 功能:第2条折线添加一个点 */ public void addLine2Data(float yValues) { addEntry(mLineData, mLineChart, yValues, LINE_NUMBER_2); } /** * 功能:第3条折线添加一个点 */ public void addLine3Data(float yValues) { addEntry(mLineData, mLineChart, yValues, LINE_NUMBER_3); } 12.自定义Handler:DemoHandler

自定义一个Handler,通过静态内部类+弱引用的方式可以很好的防止内存泄漏

封装发送和暂停方法:

/** * 功能:发送开始 */ void sendStartAddEntry() { if (!mDemoHandler.hasMessages(MSG_START)) { // 判断是否有消息队列此消息,如果没有则发送 mDemoHandler.sendEmptyMessageDelayed(MSG_START, 1000); } } /** * 功能:暂停添加点,即移除所有消息 */ void sendPauseAddEntry() { mDemoHandler.removeCallbacksAndMessages(null); }

自定义Handler

/** * 功能:自定义Handler,通过弱引用的方式防止内存泄漏 */ private static class DemoHandler extends Handler { WeakReference mReference; DemoHandler(LineChartDemo activity) { mReference = new WeakReference(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); LineChartDemo lineChartDemo = mReference.get(); if (lineChartDemo == null) { return; } switch (msg.what) { case MSG_START: lineChartDemo.addLine1Data(lineChartDemo.getRandom(30f)); lineChartDemo.addLine2Data(lineChartDemo.getRandom(20f)); lineChartDemo.addLine3Data(lineChartDemo.getRandom(10f)); lineChartDemo.sendStartAddEntry(); break; default: } } } 13. 点击事件:onClick() @Override public void onClick(View view) { switch (view.getId()) { case R.id.demo_start: sendStartAddEntry(); break; case R.id.demo_pause: sendPauseAddEntry(); break; case R.id.demo_checkbox1: showLine(LINE_NUMBER_1); break; case R.id.demo_checkbox2: showLine(LINE_NUMBER_2); break; case R.id.demo_checkbox3: showLine(LINE_NUMBER_3); break; default: } } 14.最后一步,回收:onDestory @Override protected void onDestroy() { super.onDestroy(); // 清空消息 mDemoHandler.removeCallbacksAndMessages(null); mDemoHandler = null; // moveViewToAnimated 移动到某个点,有内存泄漏,暂未修复,希望网友可以指着 mLineChart.clearAllViewportJobs(); mLineChart.removeAllViewsInLayout(); mLineChart.removeAllViews(); } 四、全部Java代码

XML,以及自定义MarkView已经在上面给出了,现在补上全部的java代码

package com.liang.batterytestsystem.module.details; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import com.github.mikephil.charting.charts.LineChart; 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.liang.batterytestsystem.R; import com.liang.batterytestsystem.utils.LColor; import com.liang.liangutils.utils.LLogX; import com.liang.liangutils.view.LTitleView; import java.lang.ref.WeakReference; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.Random; public class LineChartDemo extends AppCompatActivity implements View.OnClickListener { public static final int MSG_START = 1; // handler消息,开始添加点 // 折线编号 public static final int LINE_NUMBER_1 = 0; public static final int LINE_NUMBER_2 = 1; public static final int LINE_NUMBER_3 = 2; /** * 功能:启动方式 */ public static void startActivity(Context context) { context.startActivity(new Intent(context, LineChartDemo.class)); } private DemoHandler mDemoHandler; // 自定义Handler private Random mRandom = new Random(); // 随机产生点 private DecimalFormat mDecimalFormat = new DecimalFormat("#.00"); // 格式化浮点数位两位小数 Button mBtnStart; // 开始添加点 Button mBtnPause; // 暂停添加点 CheckBox mCheckBox1; CheckBox mCheckBox2; CheckBox mCheckBox3; List mCheckBoxList = new ArrayList(); LineChart mLineChart; // 折线表,存线集合 LineData mLineData; // 线集合,所有折现以数组的形式存到此集合中 XAxis mXAxis; //X轴 YAxis mLeftYAxis; //左侧Y轴 YAxis mRightYAxis; //右侧Y轴 Legend mLegend; //图例 LimitLine mLimitline; //限制线 // Y值数据链表 List mList1 = new ArrayList(); List mList2 = new ArrayList(); List mList3 = new ArrayList(); // Chart需要的点数据链表 List mEntries1 = new ArrayList(); List mEntries2 = new ArrayList(); List mEntries3 = new ArrayList(); // LineDataSet:点集合,即一条线 LineDataSet mLineDataSet1 = new LineDataSet(mEntries1, "折线1"); LineDataSet mLineDataSet2 = new LineDataSet(mEntries2, "折线2"); LineDataSet mLineDataSet3 = new LineDataSet(mEntries3, "折线3"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.demo_activity_line_chart); mDemoHandler = new DemoHandler(this); initView(); initLineChart(); } /** * 功能:产生随机数(小数点两位) */ public Float getRandom(Float seed) { return Float.valueOf(mDecimalFormat.format(mRandom.nextFloat() * seed)); } /** * 功能:初始化基本控件,button,checkbox */ public void initView() { mBtnStart = findViewById(R.id.demo_start); mBtnPause = findViewById(R.id.demo_pause); mCheckBox1 = findViewById(R.id.demo_checkbox1); mCheckBox2 = findViewById(R.id.demo_checkbox2); mCheckBox3 = findViewById(R.id.demo_checkbox3); mCheckBoxList.add(mCheckBox1); mCheckBoxList.add(mCheckBox2); mCheckBoxList.add(mCheckBox3); mBtnStart.setOnClickListener(this); mBtnPause.setOnClickListener(this); mCheckBox1.setOnClickListener(this); mCheckBox2.setOnClickListener(this); mCheckBox3.setOnClickListener(this); } /** * 功能:初始化LineChart */ public void initLineChart() { mLineChart = findViewById(R.id.demo_linechart); mXAxis = mLineChart.getXAxis(); // 得到x轴 mLeftYAxis = mLineChart.getAxisLeft(); // 得到侧Y轴 mRightYAxis = mLineChart.getAxisRight(); // 得到右侧Y轴 mLegend = mLineChart.getLegend(); // 得到图例 mLineData = new LineData(); mLineChart.setData(mLineData); // 设置图标基本属性 setChartBasicAttr(mLineChart); // 设置XY轴 setXYAxis(mLineChart, mXAxis, mLeftYAxis, mRightYAxis); // 添加线条 initLine(); // 设置图例 createLegend(mLegend); // 设置MarkerView setMarkerView(mLineChart); } /** * 功能:设置图标的基本属性 */ void setChartBasicAttr(LineChart lineChart) { /***图表设置***/ lineChart.setDrawGridBackground(false); //是否展示网格线 lineChart.setDrawBorders(true); //是否显示边界 lineChart.setDragEnabled(true); //是否可以拖动 lineChart.setScaleEnabled(true); // 是否可以缩放 lineChart.setTouchEnabled(true); //是否有触摸事件 //设置XY轴动画效果 //lineChart.animateY(2500); lineChart.animateX(1500); } /** * 功能:设置XY轴 */ void setXYAxis(LineChart lineChart, XAxis xAxis, YAxis leftYAxis, YAxis rightYAxis) { /***XY轴的设置***/ xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //X轴设置显示位置在底部 xAxis.setAxisMinimum(0f); // 设置X轴的最小值 xAxis.setAxisMaximum(20); // 设置X轴的最大值 xAxis.setLabelCount(20, false); // 设置X轴的刻度数量,第二个参数表示是否平均分配 xAxis.setGranularity(1f); // 设置X轴坐标之间的最小间隔 lineChart.setVisibleXRangeMaximum(5);// 当前统计图表中最多在x轴坐标线上显示的总量 //保证Y轴从0开始,不然会上移一点 leftYAxis.setAxisMinimum(0f); rightYAxis.setAxisMinimum(0f); leftYAxis.setAxisMaximum(100f); rightYAxis.setAxisMaximum(100f); leftYAxis.setGranularity(1f); rightYAxis.setGranularity(1f); leftYAxis.setLabelCount(20); lineChart.setVisibleYRangeMaximum(30, YAxis.AxisDependency.LEFT);// 当前统计图表中最多在Y轴坐标线上显示的总量 lineChart.setVisibleYRangeMaximum(30, YAxis.AxisDependency.RIGHT);// 当前统计图表中最多在Y轴坐标线上显示的总量 leftYAxis.setEnabled(false); // leftYAxis.setCenterAxisLabels(true);// 将轴标记居中 // leftYAxis.setDrawZeroLine(true); // 原点处绘制 一条线 // leftYAxis.setZeroLineColor(Color.RED); // leftYAxis.setZeroLineWidth(1f); } /** * 功能:对图表中的曲线初始化,添加三条,并且默认显示第一条 */ void initLine() { createLine(mList1, mEntries1, mLineDataSet1, LColor.Colors.RED.getColor(), mLineData, mLineChart); createLine(mList2, mEntries2, mLineDataSet2, LColor.Colors.ORANGE.getColor(), mLineData, mLineChart); createLine(mList3, mEntries3, mLineDataSet3, LColor.Colors.YELLOW.getColor(), mLineData, mLineChart); // mLineData.getDataSetCount() 总线条数 // mLineData.getEntryCount() 总点数 // mLineData.getDataSetByIndex(index).getEntryCount() 索引index处折线的总点数 // 每条曲线添加到mLineData后,从索引0处开始排列 for (int i = 0; i < mLineData.getDataSetCount(); i++) { mLineChart.getLineData().getDataSets().get(i).setVisible(false); // } showLine(LINE_NUMBER_1); } /** * 功能:根据索引显示或隐藏指定线条 */ public void showLine(int index) { mLineChart .getLineData() .getDataSets() .get(index) .setVisible(mCheckBoxList.get(index).isChecked()); mLineChart.invalidate(); } /** * 功能:动态创建一条曲线 */ private void createLine(List dataList, List entries, LineDataSet lineDataSet, int color, LineData lineData, LineChart lineChart) { 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));// Entry(x,y) entries.add(entry); } // 初始化线条 initLineDataSet(lineDataSet, color, LineDataSet.Mode.CUBIC_BEZIER); if (lineData == null) { lineData = new LineData(); lineData.addDataSet(lineDataSet); lineChart.setData(lineData); } else { lineChart.getLineData().addDataSet(lineDataSet); } lineChart.invalidate(); } /** * 曲线初始化设置,一个LineDataSet 代表一条曲线 * * @param lineDataSet 线条 * @param color 线条颜色 * @param mode */ private void initLineDataSet(LineDataSet lineDataSet, int color, LineDataSet.Mode mode) { lineDataSet.setColor(color); // 设置曲线颜色 lineDataSet.setCircleColor(color); // 设置数据点圆形的颜色 lineDataSet.setDrawCircleHole(false);// 设置曲线值的圆点是否是空心 lineDataSet.setLineWidth(1f); // 设置折线宽度 lineDataSet.setCircleRadius(3f); // 设置折现点圆点半径 lineDataSet.setValueTextSize(10f); lineDataSet.setDrawFilled(true); //设置折线图填充 lineDataSet.setFormLineWidth(1f); lineDataSet.setFormSize(15.f); if (mode == null) { //设置曲线展示为圆滑曲线(如果不设置则默认折线) lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); } else { lineDataSet.setMode(mode); } } /** * 功能:创建图例 */ private void createLegend(Legend legend) { /***折线图例 标签 设置***/ //设置显示类型,LINE CIRCLE SQUARE EMPTY 等等 多种方式,查看LegendForm 即可 legend.setForm(Legend.LegendForm.CIRCLE); legend.setTextSize(12f); //显示位置 左下方 legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); legend.setOrientation(Legend.LegendOrientation.HORIZONTAL); //是否绘制在图表里面 legend.setDrawInside(false); legend.setEnabled(true); } /** * 设置 可以显示X Y 轴自定义值的 MarkerView */ public void setMarkerView(LineChart lineChart) { LineChartMarkViewDemo mv = new LineChartMarkViewDemo(this); mv.setChartView(lineChart); lineChart.setMarker(mv); lineChart.invalidate(); } /** * 动态添加数据 * 在一个LineChart中存放的折线,其实是以索引从0开始编号的 * * @param yValues y值 */ public void addEntry(LineData lineData, LineChart lineChart, float yValues, int index) { // 通过索引得到一条折线,之后得到折线上当前点的数量 int xCount = lineData.getDataSetByIndex(index).getEntryCount(); Entry entry = new Entry(xCount, yValues); // 创建一个点 lineData.addEntry(entry, index); // 将entry添加到指定索引处的折线中 //通知数据已经改变 lineData.notifyDataChanged(); lineChart.notifyDataSetChanged(); //把yValues移到指定索引的位置 lineChart.moveViewToAnimated(xCount - 4, yValues, YAxis.AxisDependency.LEFT, 1000);// TODO: 2019/5/4 内存泄漏,异步 待修复 lineChart.invalidate(); } /** * 功能:第1条折线添加一个点 */ public void addLine1Data(float yValues) { addEntry(mLineData, mLineChart, yValues, LINE_NUMBER_1); } /** * 功能:第2条折线添加一个点 */ public void addLine2Data(float yValues) { addEntry(mLineData, mLineChart, yValues, LINE_NUMBER_2); } /** * 功能:第3条折线添加一个点 */ public void addLine3Data(float yValues) { addEntry(mLineData, mLineChart, yValues, LINE_NUMBER_3); } /** * 功能:发送开始 */ void sendStartAddEntry() { if (!mDemoHandler.hasMessages(MSG_START)) { // 判断是否有消息队列此消息,如果没有则发送 mDemoHandler.sendEmptyMessageDelayed(MSG_START, 1000); } } /** * 功能:暂停添加点,即移除所有消息 */ void sendPauseAddEntry() { mDemoHandler.removeCallbacksAndMessages(null); } @Override protected void onDestroy() { super.onDestroy(); // 清空消息 mDemoHandler.removeCallbacksAndMessages(null); mDemoHandler = null; // moveViewToAnimated 移动到某个点,有内存泄漏,暂未修复,希望网友可以指着 mLineChart.clearAllViewportJobs(); mLineChart.removeAllViewsInLayout(); mLineChart.removeAllViews(); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.demo_start: sendStartAddEntry(); break; case R.id.demo_pause: sendPauseAddEntry(); break; case R.id.demo_checkbox1: showLine(LINE_NUMBER_1); break; case R.id.demo_checkbox2: showLine(LINE_NUMBER_2); break; case R.id.demo_checkbox3: showLine(LINE_NUMBER_3); break; default: } } /** * 功能:自定义Handler,通过弱引用的方式防止内存泄漏 */ private static class DemoHandler extends Handler { WeakReference mReference; DemoHandler(LineChartDemo activity) { mReference = new WeakReference(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); LineChartDemo lineChartDemo = mReference.get(); if (lineChartDemo == null) { return; } switch (msg.what) { case MSG_START: lineChartDemo.addLine1Data(lineChartDemo.getRandom(30f)); lineChartDemo.addLine2Data(lineChartDemo.getRandom(20f)); lineChartDemo.addLine3Data(lineChartDemo.getRandom(10f)); lineChartDemo.sendStartAddEntry(); break; default: } } } }

 

 

参考:

MPAndroidChart折线图详细使用

MPAndroidChart详解

MPAndroidChart折线图(LineChart)的使用,可以左右滑动

Android统计图表MPAndroidChart:动态添加数据更新【6】

Android图表控件MPAndroidChart——曲线图LineChart(多条曲线)动态添加数据

Android图表控件MPAndroidChart的简单介绍(MPAndroidChart3.0)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3