Android LineChart绘制折线图的示例详解
作者:Bytezero! 发布时间:2022-10-15 22:43:37
标签:Android,LineChart,折线图
1.首先在 build.gradle 里导入包
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
2.新建 启动Activity
LineChartActivity 如下
**
* @Author: Bytezero_zhengLei
* @Time: 2023/3/24 10:12
* @Project_Name: LineChartActivity.java
* @Email: 420498246@qq.com
* @Description:
* @TODO: 折线图
*/
public class LineChartActivity extends AppCompatActivity {
private LineChart lineChart;
List<IncomeBean> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_line_chart);
lineChart = (LineChart) findViewById(R.id.linechart);
lineChart = MPAndroidUtil.initChart(this, lineChart);
for (int i =0; i <10; i ++){
IncomeBean incomeBean = new IncomeBean(36.5,"2020-01-01 00:00:00");
list.add(incomeBean);
}
// 开始画折线图
setLineChart(list, "BMI" + "kg/²", getResources().getColor(R.color.bule_title));
}
//设置折线
public void setLineChart(List<IncomeBean> mLineChart, String string, int color) {
lineChart = MPAndroidUtil.initChart(this, lineChart);
lineChart.setData(MPAndroidUtil.showLineChart(mLineChart, string, color));
//设置一页最大显示个数为6,超出部分就滑动
float ratio = (float) mLineChart.size() / (float) 6;
//显示的时候是按照多大的比率缩放显示,1f表示不放大缩小
// lineChart.zoom(ratio, 1f, 0, 0);
// 设置填充图
Drawable drawable = getResources().getDrawable(R.drawable.fade_blue);
MPAndroidUtil.setChartFillDrawable(drawable, lineChart);
// 设置点击的弹窗
MPAndroidUtil.setMarkerView1(lineChart);
/* lineChart.getLineData().addDataSet(MPAndroidUtil.addLine(list1, "地位条", getResources().getColor(R.color.text_orange)));
lineChart.invalidate();*/
}
}
3.新建数据 IncomeBean
/**
* @Author: Bytezero_zhengLei
* @Time: 2023/3/24 10:24
* @Project_Name: IncomeBean.java
* @Email: 420498246@qq.com
* @Description:
* @TODO:
*/
public class IncomeBean implements Serializable {
public String tradeDate;// 时间
public double value;// 数值
public IncomeBean(double mValue, String mTradeDate) {
tradeDate = mTradeDate;
value = mValue;
}
@Override
public String toString() {
return "IncomeBean{" +
"tradeDate='" + tradeDate + '\'' +
", value=" + value +
'}';
}
}
4.制定折线图的属性 MPAndroidUtil
/**
* @Author: Bytezero_zhengLei
* @Time: 2023/3/24 10:20
* @Project_Name: MPAndroidUtil.java
* @Email: 420498246@qq.com
* @Description:
* @TODO:
*/
public class MPAndroidUtil {
private static final String TAG = "MPAndroidUtil";
private static XAxis xAxis = null; //X轴
private static YAxis leftYAxis; //左侧Y轴
private static YAxis rightYaxis; //右侧Y轴
private static Legend legend; //图例
/**
* 初始化图表 折线图
*/
public static LineChart initChart(Context context, LineChart lineChart) {
/***图表设置***/
//是否展示网格线
lineChart.setDrawGridBackground(false);
//是否显示边界
lineChart.setDrawBorders(false);
//是否可以拖动
lineChart.setDragEnabled(false);
//是否有触摸事件
lineChart.setTouchEnabled(true);
// 关闭双击放大功能
lineChart.setDoubleTapToZoomEnabled(false);
//设置XY轴动画效果
lineChart.animateY(2500);
lineChart.animateX(1500);
lineChart.setBackgroundColor(context.getResources().getColor(R.color.white));
/***XY轴的设置***/
xAxis = null;
xAxis = lineChart.getXAxis();
leftYAxis = lineChart.getAxisLeft();
rightYaxis = lineChart.getAxisRight();
//X轴设置显示位置在底部
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setAxisMinimum(0f);
xAxis.setGranularity(1f);
//保证Y轴从0开始,不然会上移一点
leftYAxis.setAxisMinimum(0f);
rightYaxis.setAxisMinimum(0f);
// 但还是显示了网格线,而且不是我们想要的 虚线 。其实那是 X Y轴自己的网格线,禁掉即可
xAxis.setDrawGridLines(false);
rightYaxis.setDrawGridLines(false);
leftYAxis.setDrawGridLines(true);
//设置X Y轴网格线为虚线(实体线长度、间隔距离、偏移量:通常使用 0)
leftYAxis.enableGridDashedLine(10f, 10f, 0f);
// 目标效果图没有右侧Y轴,所以去掉右侧Y轴
rightYaxis.setEnabled(false);
/***折线图例 标签 设置***/
legend = lineChart.getLegend();
//legend.setEnabled(false);
//设置显示类型,LINE CIRCLE SQUARE EMPTY 等等 多种方式,查看LegendForm 即可
legend.setForm(Legend.LegendForm.LINE);
legend.setTextSize(12f);
//显示位置 左下方
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
legend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
//是否绘制在图表里面
legend.setDrawInside(false);
// legend.setExtra(mLegendEntries);
// lineChart.setNoDataText(context.getResources().getString(R.string.No_data));
lineChart.setNoDataText(" ");
// 设置右下角的提示
Description description = new Description();
// description.setText("需要展示的内容");
description.setEnabled(false);
lineChart.setDescription(description);
lineChart.setExtraBottomOffset(2 * 8f);
lineChart.setXAxisRenderer(new CustomXAxisRenderer(lineChart.getViewPortHandler(), lineChart.getXAxis(), lineChart.getTransformer(YAxis.AxisDependency.LEFT)));
return lineChart;
}
/**
* 曲线初始化设置 一个LineDataSet 代表一条曲线
*
* @param lineDataSet 线条
* @param color 线条颜色
* @param mode
*/
public static LineDataSet initLineDataSet(LineDataSet lineDataSet, int color, LineDataSet.Mode mode) {
lineDataSet.setColor(color);
lineDataSet.setCircleColor(color);
lineDataSet.setLineWidth(1f);
lineDataSet.setCircleRadius(2f);
//设置曲线值的圆点是实心还是空心
lineDataSet.setDrawCircleHole(true);
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);
}
// 不显示值
lineDataSet.setDrawValues(false);
return lineDataSet;
}
public static LineData showLineChart(final List<IncomeBean> dataList, String name, int color) {
List<Entry> entries = new ArrayList<>();
for (int i = 0; i < dataList.size(); i++) {
IncomeBean data = dataList.get(i);
/**
* 在此可查看 Entry构造方法,可发现 可传入数值 Entry(float x, float y)
* 也可传入Drawable, Entry(float x, float y, Drawable icon) 可在XY轴交点 设置Drawable图像展示
*/
Entry entry = new Entry(i, (float) data.value);
entries.add(entry);
}
xAxis.setValueFormatter(new IndexAxisValueFormatter() {
@Override
public String getFormattedValue(float value) {
String tradeDate;
try {
tradeDate = dataList.get((int) value % dataList.size()).tradeDate;
} catch (Exception mE) {
tradeDate = "2020-01-01 00:00:00";
}
return StrToStr("yyyy-MM-dd HH:mm:ss", "MM-dd HH:mm", tradeDate);
}
});
xAxis.setLabelCount(6, false);
leftYAxis.setLabelCount(8);
// 每一个LineDataSet代表一条线
LineDataSet lineDataSet = new LineDataSet(entries, name);
lineDataSet = initLineDataSet(lineDataSet, color, LineDataSet.Mode.CUBIC_BEZIER);
LineData lineData = new LineData(lineDataSet);
return lineData;
}
public static void setMarkerView1(LineChart lineChart) {
// LineChartMarkView1 mv = new LineChartMarkView1(MApplication.getInstance(), xAxis.getValueFormatter());
LineChartMarkView1 mv = new LineChartMarkView1(lineChart.getContext(), xAxis.getValueFormatter());
mv.setChartView(lineChart);
lineChart.setMarker(mv);
lineChart.invalidate();
}
/*
* 设置线条填充背景颜色
*
* @param drawable
*/
public static LineChart setChartFillDrawable(Drawable drawable, LineChart mLineChart) {
if (mLineChart.getData() != null && mLineChart.getData().getDataSetCount() > 0) {
LineDataSet lineDataSet = (LineDataSet) mLineChart.getData().getDataSetByIndex(0);
//避免在 initLineDataSet()方法中 设置了 lineDataSet.setDrawFilled(false); 而无法实现效果
lineDataSet.setDrawFilled(true);
lineDataSet.setFillDrawable(drawable);
mLineChart.invalidate();
}
return mLineChart;
}
// 传入某种格式的时间格式,得到特定的时间格式
public static String StrToStr(String SimpleDateFormat_in, String SimpleDateFormat_out, String str) {
SimpleDateFormat format = new SimpleDateFormat(SimpleDateFormat_in);
SimpleDateFormat format1 = new SimpleDateFormat(SimpleDateFormat_out);
Date date = null;
try {
date = format.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return format1.format(date.getTime());
}
}
5.LineChartMarkView1
**
* @Author: Bytezero_zhengLei
* @Time: 2023/3/24 10:45
* @Project_Name: LineChartMarkView1.java
* @Email: 420498246@qq.com
* @Description:
* @TODO:
*/
public class LineChartMarkView1 extends MarkerView {
private TextView tvDate;
private TextView tvValue;
private IAxisValueFormatter xAxisValueFormatter;
DecimalFormat df = new DecimalFormat(".00");
public LineChartMarkView1(Context context, IAxisValueFormatter xAxisValueFormatter) {
super(context, R.layout.layout_markview1);
this.xAxisValueFormatter = xAxisValueFormatter;
tvDate = findViewById(R.id.tv_date);
tvValue = findViewById(R.id.tv_value);
}
@SuppressLint("SetTextI18n")
@Override
public void refreshContent(Entry e, Highlight highlight) {
Chart chart = getChartView();
if (chart instanceof LineChart) {
LineData lineData = ((LineChart) chart).getLineData();
//获取到图表中的所有曲线
List<ILineDataSet> 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) {
tvValue.setText(dataSet.getLabel() + ":" + e.getY());
}
}
tvDate.setText(xAxisValueFormatter.getFormattedValue(e.getX(), null));
}
super.refreshContent(e, highlight);
}
@Override
public MPPointF getOffset() {
return new MPPointF(-(getWidth() / 2), -getHeight());
}
}
6.CustomXAxisRenderer
/**
* @Author: Bytezero_zhengLei
* @Time: 2023/3/24 10:23
* @Project_Name: CustomXAxisRenderer.java
* @Email: 420498246@qq.com
* @Description:
* @TODO:
*/
public class CustomXAxisRenderer extends XAxisRenderer {
public CustomXAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) {
super(viewPortHandler, xAxis, trans);
}
@Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
// super.drawLabel(c, formattedLabel, x, y, anchor, angleDegrees);//注释掉这个,否则坐标标签复写两次
String[] lines = formattedLabel.split(" ");
for (int i = 0; i < lines.length; i++) {
float vOffset = i * mAxisLabelPaint.getTextSize();
Utils.drawXAxisValue(c, lines[i], x, y + vOffset, mAxisLabelPaint, anchor, angleDegrees);
}
}
}
7.一些 小的 layout
LineChartMarkView1的layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_square"
android:orientation="vertical">
<TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/tv_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textColor="@android:color/white" />
</LinearLayout>
LineChartActivity中的 layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LineChart.LineChartActivity">
<com.github.mikephil.charting.charts.LineChart
android:layout_gravity="center"
android:id="@+id/linechart"
android:layout_width="match_parent"
android:layout_height="300dp" />
</LinearLayout>
这样就ok了
来源:https://www.cnblogs.com/Bytezero/p/17250982.html


猜你喜欢
- ModbusModbus是一种串行通信协议。Modbus 一个工业上常用的通讯协议、一种通讯约定。Modbus协议包括RTU、ASCII、T
- 本文实例讲述了Java matches类,Pattern类及matcher类用法。分享给大家供大家参考,具体如下:Pattern类正则表达式
- 1. 基础知识集合Java.util包下的常用子类,集合无非就是各种数据结构的应用。集合存在的目的就是为了将数据高效的进行读写,无论哪种具体
- 前言在RequestMappingHandlerAdapter对request进行了适配,并且调用了目标handler之后,其会返回一个Mo
- Controller如何进行重定向Spring MVC中进行重定向本人知道的有两种方式方法返回的URI(相对路径)中加上"redi
- 前言《英文猜词游戏》代码行数没有超过200行,是之前为了背英语单词,特意研发的小游戏。主要设计1.事先准备单词文本。2.为了让玩家能与程序互
- 前段时间,有个同事说“30000000000000000000000000000000000000000000000000000000000
- (一).前言: 这两天QQ进行了重大更新(6.X)尤其在UI风格上面由之前的蓝色换成了白色居多了,侧滑效果也发生了一些变化,那我们今天来模仿
- 1. Java中导致死锁的原因Java中死锁最简单的情况是,一个线程T1持有锁L1并且申请获得锁L2,而另一个线程T2持有锁L2并且申请获得
- 概念介绍不同的引用类型,主要体现的是对象不同的可达性(reachable)状态和对垃圾收集的影响。01. 强引用这个就
- 什么是自动装箱,拆箱先抛出定义,Java中基础数据类型与它们的包装类进行运算时,编译器会自动帮我们进行转换,转换过程对程序员是透明的,这就是
- 前言:想象一下,有一个服务提供个多个客户端调用,但不是所有客户端都需要全部的返回参数:比如商品列表服务返回商品的所有信息,而订单服务调用商品
- 英文意思随机数可以做什么?生成一些随机的数字用途非常的广泛, 例如随机抽取数据库的一条记录,把生成的数字给变量,某一个时间点执行一些代码,随
- 在Android的应用框架中,ActivityManagerService是非常重要的一个组件,尽管名字叫做ActivityManagerS
- ObjectMapper 忽略字段大小写核心代码:ObjectMapper mapper = new ObjectMapper();mapp
- 首先需要一个自定义view用来签字使用,可以修改颜色和画笔的粗细,可以擦拭重新画package com.android.tcm.view;i
- 饿汉式饿汉式:类加载就会导致该单实例对象被创建// 问题1:为什么加 final// 问题2:如果实现了序列化接口, 还要做什么来防止反序列
- 1. 我们可以通过将字符强转为int型进行输出那么在控制台中我们将会得到字符的ascii值,这里我们使用nextLine()方法来接收字符串
- 本文实例讲述了C#基于简单工厂模式实现的计算器功能。分享给大家供大家参考,具体如下:子类拥有父类除私有之外的所有属性字段和方法using S
- 本文实例为大家分享了java实现自动登录的具体代码,供大家参考,具体内容如下当你勾选(记住登录状态),用cookie保存用户名和密码。不勾选