美文网首页
MPAndroidChart(1)单条曲线图LineChart

MPAndroidChart(1)单条曲线图LineChart

作者: 古早味蛋糕 | 来源:发表于2022-10-18 22:39 被阅读0次

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

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

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

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

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

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

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


    20221018080226329.png

    1.数据准备

    1.1 数据来源

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

    json格式如下


    20221018081110372.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文件中添加


    202210186789.png

    Project 的settings.gradle文件中添加


    202210189876.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文件 或者本文相关代码

    此时的图形效果


    20221019679889.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);
    

    修改后的效果图


    20221010220978.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)+"%";
            }
        });
    

    此时的效果图


    202210200979.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) + "%";
            }
        });
    

    现在的效果图


    202210221234.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显示值自定义一样,这样显示可以一致性。
    此时的效果


    202210224456.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);
    

    之后效果如图


    20221024211134.png

    相关文章

      网友评论

          本文标题:MPAndroidChart(1)单条曲线图LineChart

          本文链接:https://www.haomeiwen.com/subject/gvhfzrtx.html