Android LineChart 折线图Demo
1 首先在 build.gradle 里导入包
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
2.新建 启动Activity
LineChartActivity 如下
1 ** 2 * @Author: Bytezero_zhengLei 3 * @Time: 2023/3/24 10:12 4 * @Project_Name: LineChartActivity.java 5 * @Email: 420498246@qq.com 6 * @Description: 7 * @TODO: 折线图 8 */ 9 10 public class LineChartActivity extends AppCompatActivity { 11 12 private LineChart lineChart; 13 List<IncomeBean> list = new ArrayList<>(); 14 15 @Override 16 protected void onCreate(Bundle savedInstanceState) { 17 super.onCreate(savedInstanceState); 18 setContentView(R.layout.activity_line_chart); 19 20 lineChart = (LineChart) findViewById(R.id.linechart); 21 22 lineChart = MPAndroidUtil.initChart(this, lineChart); 23 24 25 26 27 for (int i =0; i <10; i ++){ 28 IncomeBean incomeBean = new IncomeBean(36.5,"2020-01-01 00:00:00"); 29 list.add(incomeBean); 30 31 } 32 33 // 开始画折线图 34 setLineChart(list, "BMI" + "kg/²", getResources().getColor(R.color.bule_title)); 35 } 36 37 38 //设置折线 39 40 41 public void setLineChart(List<IncomeBean> mLineChart, String string, int color) { 42 lineChart = MPAndroidUtil.initChart(this, lineChart); 43 lineChart.setData(MPAndroidUtil.showLineChart(mLineChart, string, color)); 44 //设置一页最大显示个数为6,超出部分就滑动 45 float ratio = (float) mLineChart.size() / (float) 6; 46 //显示的时候是按照多大的比率缩放显示,1f表示不放大缩小 47 // lineChart.zoom(ratio, 1f, 0, 0); 48 // 设置填充图 49 Drawable drawable = getResources().getDrawable(R.drawable.fade_blue); 50 MPAndroidUtil.setChartFillDrawable(drawable, lineChart); 51 // 设置点击的弹窗 52 MPAndroidUtil.setMarkerView1(lineChart); 53 54 55 /* lineChart.getLineData().addDataSet(MPAndroidUtil.addLine(list1, "地位条", getResources().getColor(R.color.text_orange))); 56 lineChart.invalidate();*/ 57 58 } 59 }
3.新建数据 IncomeBean
1 /** 2 * @Author: Bytezero_zhengLei 3 * @Time: 2023/3/24 10:24 4 * @Project_Name: IncomeBean.java 5 * @Email: 420498246@qq.com 6 * @Description: 7 * @TODO: 8 */ 9 10 public class IncomeBean implements Serializable { 11 public String tradeDate;// 时间 12 public double value;// 数值 13 14 public IncomeBean(double mValue, String mTradeDate) { 15 tradeDate = mTradeDate; 16 value = mValue; 17 } 18 19 @Override 20 public String toString() { 21 return "IncomeBean{" + 22 "tradeDate='" + tradeDate + '\'' + 23 ", value=" + value + 24 '}'; 25 } 26 }
4.制定折线图的属性 MPAndroidUtil
1 /** 2 * @Author: Bytezero_zhengLei 3 * @Time: 2023/3/24 10:20 4 * @Project_Name: MPAndroidUtil.java 5 * @Email: 420498246@qq.com 6 * @Description: 7 * @TODO: 8 */ 9 10 public class MPAndroidUtil { 11 private static final String TAG = "MPAndroidUtil"; 12 private static XAxis xAxis = null; //X轴 13 private static YAxis leftYAxis; //左侧Y轴 14 private static YAxis rightYaxis; //右侧Y轴 15 private static Legend legend; //图例 16 17 18 /** 19 * 初始化图表 折线图 20 */ 21 public static LineChart initChart(Context context, LineChart lineChart) { 22 23 /***图表设置***/ 24 //是否展示网格线 25 lineChart.setDrawGridBackground(false); 26 //是否显示边界 27 lineChart.setDrawBorders(false); 28 //是否可以拖动 29 lineChart.setDragEnabled(false); 30 //是否有触摸事件 31 lineChart.setTouchEnabled(true); 32 // 关闭双击放大功能 33 lineChart.setDoubleTapToZoomEnabled(false); 34 //设置XY轴动画效果 35 lineChart.animateY(2500); 36 lineChart.animateX(1500); 37 38 lineChart.setBackgroundColor(context.getResources().getColor(R.color.white)); 39 40 41 /***XY轴的设置***/ 42 xAxis = null; 43 xAxis = lineChart.getXAxis(); 44 leftYAxis = lineChart.getAxisLeft(); 45 rightYaxis = lineChart.getAxisRight(); 46 //X轴设置显示位置在底部 47 xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); 48 xAxis.setAxisMinimum(0f); 49 xAxis.setGranularity(1f); 50 //保证Y轴从0开始,不然会上移一点 51 leftYAxis.setAxisMinimum(0f); 52 rightYaxis.setAxisMinimum(0f); 53 54 // 但还是显示了网格线,而且不是我们想要的 虚线 。其实那是 X Y轴自己的网格线,禁掉即可 55 xAxis.setDrawGridLines(false); 56 rightYaxis.setDrawGridLines(false); 57 leftYAxis.setDrawGridLines(true); 58 //设置X Y轴网格线为虚线(实体线长度、间隔距离、偏移量:通常使用 0) 59 leftYAxis.enableGridDashedLine(10f, 10f, 0f); 60 // 目标效果图没有右侧Y轴,所以去掉右侧Y轴 61 rightYaxis.setEnabled(false); 62 63 /***折线图例 标签 设置***/ 64 legend = lineChart.getLegend(); 65 //legend.setEnabled(false); 66 //设置显示类型,LINE CIRCLE SQUARE EMPTY 等等 多种方式,查看LegendForm 即可 67 legend.setForm(Legend.LegendForm.LINE); 68 legend.setTextSize(12f); 69 //显示位置 左下方 70 legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); 71 legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); 72 legend.setOrientation(Legend.LegendOrientation.HORIZONTAL); 73 //是否绘制在图表里面 74 legend.setDrawInside(false); 75 // legend.setExtra(mLegendEntries); 76 77 // lineChart.setNoDataText(context.getResources().getString(R.string.No_data)); 78 lineChart.setNoDataText(" "); 79 // 设置右下角的提示 80 Description description = new Description(); 81 // description.setText("需要展示的内容"); 82 description.setEnabled(false); 83 lineChart.setDescription(description); 84 85 lineChart.setExtraBottomOffset(2 * 8f); 86 87 lineChart.setXAxisRenderer(new CustomXAxisRenderer(lineChart.getViewPortHandler(), lineChart.getXAxis(), lineChart.getTransformer(YAxis.AxisDependency.LEFT))); 88 return lineChart; 89 } 90 91 92 /** 93 * 曲线初始化设置 一个LineDataSet 代表一条曲线 94 * 95 * @param lineDataSet 线条 96 * @param color 线条颜色 97 * @param mode 98 */ 99 public static LineDataSet initLineDataSet(LineDataSet lineDataSet, int color, LineDataSet.Mode mode) { 100 lineDataSet.setColor(color); 101 lineDataSet.setCircleColor(color); 102 lineDataSet.setLineWidth(1f); 103 lineDataSet.setCircleRadius(2f); 104 //设置曲线值的圆点是实心还是空心 105 lineDataSet.setDrawCircleHole(true); 106 lineDataSet.setValueTextSize(10f); 107 //设置折线图填充 108 lineDataSet.setDrawFilled(true); 109 lineDataSet.setFormLineWidth(1f); 110 lineDataSet.setFormSize(15.f); 111 if (mode == null) { 112 //设置曲线展示为圆滑曲线(如果不设置则默认折线) 113 lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); 114 } else { 115 lineDataSet.setMode(mode); 116 } 117 // 不显示值 118 lineDataSet.setDrawValues(false); 119 return lineDataSet; 120 121 } 122 123 public static LineData showLineChart(final List<IncomeBean> dataList, String name, int color) { 124 List<Entry> entries = new ArrayList<>(); 125 for (int i = 0; i < dataList.size(); i++) { 126 IncomeBean data = dataList.get(i); 127 /** 128 * 在此可查看 Entry构造方法,可发现 可传入数值 Entry(float x, float y) 129 * 也可传入Drawable, Entry(float x, float y, Drawable icon) 可在XY轴交点 设置Drawable图像展示 130 */ 131 Entry entry = new Entry(i, (float) data.value); 132 entries.add(entry); 133 } 134 xAxis.setValueFormatter(new IndexAxisValueFormatter() { 135 @Override 136 public String getFormattedValue(float value) { 137 String tradeDate; 138 try { 139 tradeDate = dataList.get((int) value % dataList.size()).tradeDate; 140 } catch (Exception mE) { 141 tradeDate = "2020-01-01 00:00:00"; 142 } 143 144 return StrToStr("yyyy-MM-dd HH:mm:ss", "MM-dd HH:mm", tradeDate); 145 } 146 }); 147 148 149 xAxis.setLabelCount(6, false); 150 151 leftYAxis.setLabelCount(8); 152 // 每一个LineDataSet代表一条线 153 LineDataSet lineDataSet = new LineDataSet(entries, name); 154 lineDataSet = initLineDataSet(lineDataSet, color, LineDataSet.Mode.CUBIC_BEZIER); 155 LineData lineData = new LineData(lineDataSet); 156 return lineData; 157 158 } 159 160 public static void setMarkerView1(LineChart lineChart) { 161 // LineChartMarkView1 mv = new LineChartMarkView1(MApplication.getInstance(), xAxis.getValueFormatter()); 162 LineChartMarkView1 mv = new LineChartMarkView1(lineChart.getContext(), xAxis.getValueFormatter()); 163 mv.setChartView(lineChart); 164 lineChart.setMarker(mv); 165 lineChart.invalidate(); 166 } 167 168 169 /* 170 * 设置线条填充背景颜色 171 * 172 * @param drawable 173 */ 174 public static LineChart setChartFillDrawable(Drawable drawable, LineChart mLineChart) { 175 if (mLineChart.getData() != null && mLineChart.getData().getDataSetCount() > 0) { 176 LineDataSet lineDataSet = (LineDataSet) mLineChart.getData().getDataSetByIndex(0); 177 //避免在 initLineDataSet()方法中 设置了 lineDataSet.setDrawFilled(false); 而无法实现效果 178 lineDataSet.setDrawFilled(true); 179 lineDataSet.setFillDrawable(drawable); 180 181 mLineChart.invalidate(); 182 183 } 184 return mLineChart; 185 } 186 187 188 // 传入某种格式的时间格式,得到特定的时间格式 189 public static String StrToStr(String SimpleDateFormat_in, String SimpleDateFormat_out, String str) { 190 SimpleDateFormat format = new SimpleDateFormat(SimpleDateFormat_in); 191 SimpleDateFormat format1 = new SimpleDateFormat(SimpleDateFormat_out); 192 Date date = null; 193 try { 194 date = format.parse(str); 195 } catch (ParseException e) { 196 e.printStackTrace(); 197 } 198 return format1.format(date.getTime()); 199 } 200 201 202 }
5.LineChartMarkView1
1 ** 2 * @Author: Bytezero_zhengLei 3 * @Time: 2023/3/24 10:45 4 * @Project_Name: LineChartMarkView1.java 5 * @Email: 420498246@qq.com 6 * @Description: 7 * @TODO: 8 */ 9 10 public class LineChartMarkView1 extends MarkerView { 11 12 private TextView tvDate; 13 private TextView tvValue; 14 private IAxisValueFormatter xAxisValueFormatter; 15 DecimalFormat df = new DecimalFormat(".00"); 16 17 public LineChartMarkView1(Context context, IAxisValueFormatter xAxisValueFormatter) { 18 super(context, R.layout.layout_markview1); 19 this.xAxisValueFormatter = xAxisValueFormatter; 20 21 tvDate = findViewById(R.id.tv_date); 22 tvValue = findViewById(R.id.tv_value); 23 } 24 25 @SuppressLint("SetTextI18n") 26 @Override 27 public void refreshContent(Entry e, Highlight highlight) { 28 Chart chart = getChartView(); 29 if (chart instanceof LineChart) { 30 LineData lineData = ((LineChart) chart).getLineData(); 31 //获取到图表中的所有曲线 32 List<ILineDataSet> dataSetList = lineData.getDataSets(); 33 for (int i = 0; i < dataSetList.size(); i++) { 34 LineDataSet dataSet = (LineDataSet) dataSetList.get(i); 35 //获取到曲线的所有在Y轴的数据集合,根据当前X轴的位置 来获取对应的Y轴值 36 float y = dataSet.getValues().get((int) e.getX()).getY(); 37 if (i == 0) { 38 tvValue.setText(dataSet.getLabel() + ":" + e.getY()); 39 } 40 } 41 tvDate.setText(xAxisValueFormatter.getFormattedValue(e.getX(), null)); 42 } 43 44 super.refreshContent(e, highlight); 45 } 46 47 @Override 48 public MPPointF getOffset() { 49 return new MPPointF(-(getWidth() / 2), -getHeight()); 50 51 } 52 }
6.CustomXAxisRenderer
1 /** 2 * @Author: Bytezero_zhengLei 3 * @Time: 2023/3/24 10:23 4 * @Project_Name: CustomXAxisRenderer.java 5 * @Email: 420498246@qq.com 6 * @Description: 7 * @TODO: 8 */ 9 10 public class CustomXAxisRenderer extends XAxisRenderer { 11 public CustomXAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) { 12 super(viewPortHandler, xAxis, trans); 13 } 14 15 @Override 16 protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) { 17 // super.drawLabel(c, formattedLabel, x, y, anchor, angleDegrees);//注释掉这个,否则坐标标签复写两次 18 String[] lines = formattedLabel.split(" "); 19 for (int i = 0; i < lines.length; i++) { 20 float vOffset = i * mAxisLabelPaint.getTextSize(); 21 Utils.drawXAxisValue(c, lines[i], x, y + vOffset, mAxisLabelPaint, anchor, angleDegrees); 22 } 23 } 24 }
5.一些 小的 layout
LineChartMarkView1的layout
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="wrap_content" 3 android:layout_height="wrap_content" 4 android:background="@drawable/shape_square" 5 android:orientation="vertical"> 6 7 <TextView 8 android:id="@+id/tv_date" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:textColor="@android:color/white" /> 12 13 <TextView 14 android:id="@+id/tv_value" 15 android:layout_width="wrap_content" 16 android:layout_height="wrap_content" 17 android:layout_marginTop="5dp" 18 android:textColor="@android:color/white" /> 19 </LinearLayout>
6.LineChartActivity中的 layout
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 tools:context=".LineChart.LineChartActivity"> 7 8 <com.github.mikephil.charting.charts.LineChart 9 android:layout_gravity="center" 10 android:id="@+id/linechart" 11 android:layout_width="match_parent" 12 android:layout_height="300dp" /> 13 14 15 16 17 18 </LinearLayout>
这样就ok了
本文来自博客园,作者:Bytezero!,转载请注明原文链接:https://www.cnblogs.com/Bytezero/p/17250982.html