MPAndroidChart(1)单条曲线图LineChart

一、前言:
发现最新的MPAndroidChart和以前版本的使用有一些差距,就写下了现在新版的使用方法
注:2022-10-18 更新,当前MPAndroidChart版本:3.1.0
本文涉及文章
Android图表控件MPAndroidChart的简单介绍(MPAndroidChart3.0)

Android图表控件MPAndroidChart——曲线图LineChart的使用(多条曲线)

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

Android图表控件MPAndroidChart——柱状图BarChart的使用(多条柱状图)

Android图表控件MPAndroidChart——曲线图+柱状图 CombinedChart的使用

Android图表控件MPAndroidChart——LineChart实现 X、Y轴以及原点线的直尺刻度样式

本文将要实现的图表效果,个人财富收益图。


1.png

1.数据准备

1.1 数据来源

数据是抓包佣金宝的数据,将获取的数据存入.json文件。

json格式如下


2.png

Json 文件地址:
https://gitee.com/zyd_gitee/android-mp-charts/blob/master/app/src/main/assets/line_chart.json

2.曲线展示

2.1 MPAndroidChart获取

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

依赖:
Project 的build.gradle文件中添加


3.png

Project 的settings.gradle文件中添加


4.png

然后在 module中的build,gradle 中添加

implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'

然而大多情况下,我们会根据自己的需求自定义MPAndroidChart库,则需要下载源码并将MPChartLib引入自己的项目中。

2.2 数据对象获取

在Android Studio app项目src同级目录下新建中新建assets文件夹,然后将步骤1.1得到的.json文件放入改文件夹中。

然后在获取.json文件中的json字符串并解析为对应的数据对象,可参考以下文章

相关文章:Android访问assets本地Json文件

在此就不详叙述了,只是列出图表展示所需要的类

/**
 * 收益
 */
public class IncomeBean {
    /**
     * tradeDate : 20180502
     * value : 0.03676598
     */
    private String tradeDate;
    private double value;
}

/**
 * 沪深创指数
 */
public class CompositeIndexBean {
    /**
     * rate : -0.00034196
     * tradeDate : 20180502
     */
    private String rate;
    private String tradeDate;
}
2.3 数据展示

2.3.1 LineChart 图表初始化设置

LineChart曲线图表一会使用到如下属性

private LineChart lineChart;
private XAxis xAxis;                //X轴
private YAxis leftYAxis;            //左侧Y轴
private YAxis rightYaxis;           //右侧Y轴
private Legend legend;              //图例
private LimitLine limitLine;        //限制线
//  private MyMarkerView markerView;    //标记视图 即点击xy轴交点时弹出展示信息的View 需自定义

然后进行相应的设置

/**
 * 初始化图表
 */
private void initChart(LineChart lineChart) {
    /***图表设置***/
    //是否展示网格线
    lineChart.setDrawGridBackground(false);
    //是否显示边界
    lineChart.setDrawBorders(true);
    //是否可以拖动
    lineChart.setDragEnabled(false);
    //是否有触摸事件
    lineChart.setTouchEnabled(true);
    //设置XY轴动画效果
    lineChart.animateY(2500);
    lineChart.animateX(1500);

    /***XY轴的设置***/
    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);

    /***折线图例 标签 设置***/
    legend = lineChart.getLegend();
    //设置显示类型,LINE CIRCLE SQUARE EMPTY 等等 多种方式,查看LegendForm 即可
    legend.setForm(Legend.LegendForm.LINE);
    legend.setTextSize(12f);
    //显示位置 左下方
                legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
    legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
    legend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
    //是否绘制在图表里面
    legend.setDrawInside(false);
}

2.3.2 LineDataSet 曲线初始化设置

/**
 * 曲线初始化设置 一个LineDataSet 代表一条曲线
 *
 * @param lineDataSet 线条
 * @param color       线条颜色
 * @param mode
 */
private void initLineDataSet(LineDataSet lineDataSet, int color, LineDataSet.Mode mode) {
    lineDataSet.setColor(color);
    lineDataSet.setCircleColor(color);
    lineDataSet.setLineWidth(1f);
    lineDataSet.setCircleRadius(3f);
    //设置曲线值的圆点是实心还是空心
    lineDataSet.setDrawCircleHole(true);
    lineDataSet.setValueTextSize(10f);
    //设置折线图填充
    lineDataSet.setDrawFilled(true);
    lineDataSet.setFormLineWidth(1f);
    lineDataSet.setFormSize(15.f);
    //设置曲线展示为圆滑曲线(如果不设置则默认折线)
    lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
}

2.3.3 曲线展示

/**
 * 展示曲线
 *
 * @param dataList 数据集合
 * @param name     曲线名称
 * @param color    曲线颜色
 */
public void showLineChart(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.getValue());
        entries.add(entry);
     }
    // 每一个LineDataSet代表一条线
    LineDataSet lineDataSet = new LineDataSet(entries, name);
    initLineDataSet(lineDataSet, color, LineDataSet.Mode.LINEAR);
    LineData lineData = new LineData(lineDataSet);
    lineChart.setData(lineData);
}

然后在Activity中调用

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_line_chart);
    lineChart = findViewById(R.id.lineChart);
    initChart(lineChart);
    LineChartBean lineChartBean = LocalJsonAnalyzeUtil.JsonToObject(this,
        "chart.json", LineChartBean.class);
    List<IncomeBean> list = lineChartBean.getGRID0().getResult().getClientAccumulativeRate();
    showLineChart(list, "收益", Color.CYAN);
}

注意:不了解数据怎么来的可查看 相关文章:Android访问assets本地Json文件 或者本文相关代码

此时的图形效果


5.png

线性图是有了,但离需要达到的效果差了很多很多,所有需要一点点的完善。

3.曲线完善

首先总结哪里需要进行修改完善,然后一一进行修改,需要的修改的地方如下。

  • 图表背景、边框、网格的修改
  • X Y轴值的自定义
  • 线条的渐变背景、值、点 的修改
  • MarkerView的实现
  • X轴的位置、X Y 轴的刻度展示(需要修改源码、放最后来处理)
3.1 图表背景、边框、网格线修改

修改背景,去掉边框

lineChart.setBackgroundColor(Color.WHITE);
//是否显示边界
lineChart.setDrawBorders(false);

网格线修改
在2.3.1的时候已经设置了禁止显示网格线

//是否展示网格线
lineChart.setDrawGridBackground(false);

但还是显示了网格线,而且不是我们想要的 虚线 。其实那是 X Y轴自己的网格线,禁掉即可

xAxis.setDrawGridLines(false);
rightYaxis.setDrawGridLines(false);
leftYAxis.setDrawGridLines(true);

设置X Y轴网格线为虚线(实体线长度、间隔距离、偏移量:通常使用 0)

leftYAxis.enableGridDashedLine(10f, 10f, 0f);

目标效果图没有右侧Y轴,所以去掉右侧Y轴

rightYaxis.setEnabled(false);

修改后的效果图


6.png
3.2 X Y轴值的自定义

目标图的效果是 X轴显示日期,Y轴显示百分比而且均分10份
数据获取到的时间为 20180502 我们需要显示 05-02 所以需要进行日期转换
一个日期转换工具

public class TimeUtil {

    public static String formatTime(String str) {
        SimpleDateFormat sf1 = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sf2 = new SimpleDateFormat("MM-dd");
        String formatStr = "";
        try {
            formatStr = sf2.format(sf1.parse(str));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return formatStr;
    }
}

X轴值的定义
在 showLineChart 方法中我们会传入X轴的值,所以自定义X轴的值可以 写在该方法内

xAxis.setValueFormatter(new ValueFormatter() {
        @Override
        public String getAxisLabel(float value, AxisBase axis) {
            String tradeDate = dataList.get((int) value).getTradeDate();
            return TimeUtil.formatTime(tradeDate);
        }
    });

X轴的间隔的实现,数据一共有18条,目标图是按照3天一间隔(因为无周末数据的关系,日期上看可能不是那样)
设置X轴分割数量

xAxis.setLabelCount(6,false);

true代表强制均分,可能会导致数据显示不均匀

Y轴值的自定义
与X轴值得自定义类似,并按照目标图的分割要求一样 将Y轴分为 8份

//设置Y轴分割数量
leftYAxis.setLabelCount(8);
leftYAxis.setValueFormatter(new ValueFormatter() {
        @Override
        public String getAxisLabel(float value, AxisBase axis) {
            return (int)(value*100)+"%";
        }
    });

此时的效果图


7.png
3.3 线条的渐变背景、值、点的修改

线条渐变背景
新建一个方法

/**
 * 设置线条填充背景颜色
 *
 * @param drawable
 */
public void setChartFillDrawable(Drawable drawable) {
    if (lineChart.getData() != null && lineChart.getData().getDataSetCount() > 0) {
        LineDataSet lineDataSet = (LineDataSet) lineChart.getData().getDataSetByIndex(0);
        //避免在 initLineDataSet()方法中 设置了 lineDataSet.setDrawFilled(false); 而无法实现效果
        lineDataSet.setDrawFilled(true);
        lineDataSet.setFillDrawable(drawable);
        lineChart.invalidate();
    }
}

然后在drawable 文件中 创建渐变样式 fade_blue.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
    android:angle="90"
    android:endColor="#FF6FA9E1"
    android:startColor="#00ff0000" />
</shape>

再调用该方法

    showLineChart(list, "收益", ContextCompat.getColor(this,R.color.blue));
    //线条的渐变背景
    Drawable drawable = ContextCompat.getDrawable(this,R.drawable.fade_blue);
    setChartFillDrawable(drawable);

线条点和值的更改
不显示点,在 initLineDataSet方法中添加

 lineDataSet.setDrawCircles(false);

线条值的更改

目标图的效果是不显示值,但有时候还是会要求显示值,而且还要求更高线条X值的显示内容
所以在此介绍一下更改 曲线显示自定义X值的内容

lineDataSet.setValueFormatter(new ValueFormatter() {
        @Override
        public String getFormattedValue(float value) {
            return String.format("%.2f",value * 100) + "%";
        }
    });

现在的效果图


8.png

曲线上不显示值

lineDataSet.setDrawValues(false);
3.4 MarkerView的实现

要求是点击曲线的点,然后弹出一个View 显示当前的日期,以及我的收益

即 MarkView 显示X Y 轴的值
1.搭建MarkView的布局文件 layout_line_mark_view

<?xml version="1.0" encoding="utf-8"?>
<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>

其中背景 shape_square.xml 是圆角透明灰背景

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="5dp" />
<stroke
    android:width="1px"
    android:color="@color/transparent_gray" />
<solid android:color="@color/transparent_gray" />
<padding
    android:bottom="5dp"
    android:left="5dp"
    android:right="5dp"
    android:top="5dp" />
</shape>

2.自定义MarkerView

public class LineChartMarkView extends MarkerView {

private TextView tvDate;
private TextView tvValue;
private ValueFormatter xAxisValueFormatter;
private ValueFormatter yAxisValueFormatter;

public LineChartMarkView(Context context,ValueFormatter xAxisValueFormatter,ValueFormatter yAxisValueFormatter) {
    super(context, R.layout.layout_line_mark_view);
    this.xAxisValueFormatter = xAxisValueFormatter;
    this.yAxisValueFormatter = yAxisValueFormatter;

    tvDate = findViewById(R.id.tv_date);
    tvValue = findViewById(R.id.tv_value);
}

@SuppressLint("SetTextI18n")
@Override
public void refreshContent(Entry e, Highlight highlight) {
    //展示自定义X轴值 后的X轴内容
    tvDate.setText(xAxisValueFormatter.getAxisLabel(e.getX(), null));
    tvValue.setText("我的收益:" +yAxisValueFormatter.getAxisLabel(e.getY(),null));
    super.refreshContent(e, highlight);
}

 @Override
 public MPPointF getOffset() {
    return new MPPointF(-(getWidth() / 2), -getHeight());
 }
}

3.设置MarkView

    /**
     * 设置 可以显示X Y 轴自定义值的 MarkerView
     */
public void setMarkerView(LineChart lineChart) {
    LineChartMarkView mv = new LineChartMarkView(this, xAxis.getValueFormatter(),leftYAxis.getValueFormatter());
    mv.setChartView(lineChart);
    lineChart.setMarker(mv);
    lineChart.invalidate();
}

调用该方法即可
注意y轴自定义要和lineDataSet显示值自定义一样,这样显示可以一致性。
此时的效果


9.png
3.5 X轴的位置调整、以及X Y 轴的刻度显示

X Y 轴的刻度显示,以及位置调整可查看我的另一篇文章

相关文章:Android图表控件MPAndroidChart——LineChart实现 X、Y轴以及原点线的直尺刻度样式
发现图表的右下角还有一个描述标签 Descripition Lable 需要在LineChart初始化时设置一下

Description description = new Description();
// description.setText("需要展示的内容");
description.setEnabled(false);
lineChart.setDescription(description);

之后效果如图


10.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容