MPAndroidChart 库LineChart使用总结

`LineChart` 是 MPAndroidChart 库中的一个组件,用于绘制曲线图。下面总结了一些 `LineChart` 常用的用例和方法:

1. **基本设置:**
   - 创建 `LineChart` 实例:`LineChart lineChart = new LineChart(context);`
   - 设置描述文本是否可见:`lineChart.getDescription().setEnabled(false);`
   - 设置是否启用双击缩放:`lineChart.setDoubleTapToZoomEnabled(false);`
   - 设置 X 轴数值格式化:`lineChart.getXAxis().setValueFormatter(new XAxisValueFormatter());`
   - 设置图表选中监听器:`lineChart.setOnChartValueSelectedListener(new OnChartValueSelectedListenerImpl());`
   - 设置 X 轴的位置:`lineChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);`
   - 设置动画效果:`lineChart.animateXY(1000, 1000);`

2. **坐标轴设置:**
   - 获取左侧 Y 轴:`YAxis leftAxis = lineChart.getAxisLeft();`
   - 获取右侧 Y 轴:`YAxis rightAxis = lineChart.getAxisRight();`
   - 启用/禁用 Y 轴网格线:`leftAxis.setDrawGridLines(true);`
   - 设置 Y 轴网格线颜色:`leftAxis.setGridColor(Color.BLACK);`
   - 设置 Y 轴网格线间距:`leftAxis.setGranularity(3f);`
   - 设置 Y 轴标签是否显示:`leftAxis.setDrawLabels(true);`
   - 设置 Y 轴最小值:`leftAxis.setAxisMinimum(0f);`
   - 设置 Y 轴最大值:`leftAxis.setAxisMaximum(10f);`

3. **限制线:**
   - 添加限制线到左侧 Y 轴:`LimitLine limitLine = new LimitLine(3.5f, "Upper Limit"); leftAxis.addLimitLine(limitLine);`

4. **MarkerView:**
   - 自定义 MarkerView:`CustomMarkerView markerView = new CustomMarkerView(context, R.layout.custom_marker_view); lineChart.setMarker(markerView);`

5. **数据设置:**
   - 创建 `LineDataSet` 实例:`LineDataSet dataSet = new LineDataSet(entries, "Label");`
   - 配置 `LineDataSet` 属性:颜色、线宽、点半径等
   - 创建 `LineData` 实例:`LineData lineData = new LineData(dataSet);`
   - 设置图表数据:`lineChart.setData(lineData);`
   - 刷新图表:`lineChart.invalidate();`

6. **值选中监听器:**
   - 实现 `OnChartValueSelectedListener` 接口:`private class OnChartValueSelectedListenerImpl implements OnChartValueSelectedListener { ... }`

7. **自定义 X 轴标签格式:**
   - 创建自定义的 `ValueFormatter` 类,继承自 `com.github.mikephil.charting.formatter.ValueFormatter`。

8. **动态更新图表数据:**
   - 添加单个数据点:`lineDataSet.addEntry(entry);`
   - 更新图表:`lineChart.notifyDataSetChanged(); lineChart.invalidate();`

以上总结包括了基本设置、坐标轴设置、限制线、MarkerView、数据设置、值选中监听器、自定义 X 轴标签格式以及动态更新图表数据等常用用例和方法。您可以根据实际需求在这些基础上进行更多的定制和扩展。

package com.jaredrummler.compent;

import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.widget.TextView;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.MarkerView;
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.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.github.mikephil.charting.utils.MPPointF;
import com.jaredrummler.materialspinner.example.R;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;


public class RecordLineChart {
    private final LineChart lineChart;
    private final Context context;

    private static List dataSets;

    public RecordLineChart(Context context, LineChart lineChart) {
        this.context = context;
        this.lineChart = lineChart;
        initializeChart();
    }

    private void initializeChart() {
        lineChart.getDescription().setEnabled(false);
        lineChart.setDoubleTapToZoomEnabled(false);
        lineChart.getXAxis().setValueFormatter(new XAxisValueFormatter());
        lineChart.setOnChartValueSelectedListener(new OnChartValueSelectedListenerImpl());
        XAxis xAxis = lineChart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); // Set the position to bottom
//        xAxis.setDrawGridLines(true);
//        lineChart.animateX(1000);
        lineChart.animateXY(1000,1000);


        YAxis leftAxis = lineChart.getAxisLeft();
        leftAxis.setDrawGridLines(true); // 启用 Y 轴的网格线
//        leftAxis.setGridColor(Color.BLACK);
        leftAxis.setGranularity(3f); // 设置 Y 轴的网格线间距
        leftAxis.setGranularityEnabled(true); // 启用 Y 轴的网格线间距
        leftAxis.setDrawLabels(true); // 不显示 Y 轴标签
//        leftAxis.setAxisMinimum(0f); // 设置 Y 轴的最小值为 0
//        leftAxis.setGranularity(1f); // Set the granularity to control the number of labels
//        leftAxis.setLabelCount(2, true); // Set the number of labels to be displayed

        YAxis rightAxis = lineChart.getAxisRight();
        rightAxis.setDrawGridLines(true); // 启用 Y 轴的网格线
//        rightAxis.setGridColor(Color.BLACK);
        rightAxis.setGranularity(3f); // 设置 Y 轴的网格线间距
        rightAxis.setGranularityEnabled(true); // 启用 Y 轴的网格线间距
        rightAxis.setDrawLabels(true); // 不显示 Y 轴标签
//        rightAxis.setAxisMinimum(0f); // 设置 Y 轴的最小值为 0
//        rightAxis.setGranularity(1f); // Set the granularity to control the number of labels
//        rightAxis.setLabelCount(2, true); // Set the number of labels to 0 to hide them
//        rightAxis.setGridColor(Color.TRANSPARENT); // Set the color of the right grid lines to transparent




        // Set MarkerView
        CustomMarkerView markerView = new CustomMarkerView(context, R.layout.custom_marker_view);
        lineChart.setMarker(markerView);
    }

    public void setData(List dataSets) {
        this.dataSets = dataSets;

        LineData lineData = new LineData();
        for (BloodSugarDataSet dataSet : dataSets) {
            lineData.addDataSet(dataSet.getLineDataSet());
            addLimitLine(dataSet);
        }

        lineChart.clear();
        lineChart.setData(lineData);
        lineChart.invalidate();
    }

    private void addLimitLine(BloodSugarDataSet dataSet) {
        // 添加血糖范围线
        LimitLine lowerLimit = new LimitLine(dataSet.getLowerLimitValue(), "");
        lowerLimit.setLineWidth(2f);
        lowerLimit.enableDashedLine(10f, 10f, 0f);
        lowerLimit.setLineColor(Color.BLUE);

        LimitLine upperLimit = new LimitLine(dataSet.getUpperLimitValue(), "");
        upperLimit.setLineWidth(2f);
        upperLimit.enableDashedLine(10f, 10f, 0f);
        upperLimit.setLineColor(Color.RED);

        lineChart.getAxisLeft().addLimitLine(lowerLimit);
        lineChart.getAxisLeft().addLimitLine(upperLimit);
    }

    public void addData(BloodSugarData data, int dataSetIndex) {
        if (dataSetIndex >= 0 && dataSetIndex < dataSets.size()) {
            BloodSugarDataSet dataSet = dataSets.get(dataSetIndex);
            dataSet.addData(data);
            updateChart();
        }
    }

    public void updateChart() {
        LineData lineData = lineChart.getData();
        if (lineData != null) {
            lineData.notifyDataChanged();
            lineChart.notifyDataSetChanged();
            lineChart.invalidate();
        }
    }



    private class OnChartValueSelectedListenerImpl implements OnChartValueSelectedListener {
        @Override
        public void onValueSelected(Entry e, Highlight h) {

        }

        @Override
        public void onNothingSelected() {
            // Handle nothing selected

        }
    }



    private static class XAxisValueFormatter extends com.github.mikephil.charting.formatter.ValueFormatter {
        @Override
        public String getAxisLabel(float value, com.github.mikephil.charting.components.AxisBase axis) {
//            SimpleDateFormat sdf = new SimpleDateFormat("MM/dd", Locale.getDefault());
//            String xLabel = sdf.format(new Date((long) value));
//            Log.i("TAG", value + "getAxisLabel: " + xLabel);
//            return xLabel;

            return dataSets.get(0).bloodSugarList.get((int) value).getDate();
        }
    }

    private static class CustomMarkerView extends MarkerView {
        private final TextView tvBloodSugar;
        private final TextView tvTimePeriod;
        private final TextView tvMeasurementTime;

        public CustomMarkerView(Context context, int layoutResource) {
            super(context, layoutResource);
            tvBloodSugar = findViewById(R.id.tvContent);
            tvTimePeriod = findViewById(R.id.tvPeriod);
            tvMeasurementTime = findViewById(R.id.tvTime);
        }

        @Override
        public void refreshContent(Entry e, Highlight highlight) {
            if (e != null ) {
                BloodSugarData data = (BloodSugarData) e.getData();
                tvBloodSugar.setText("血糖值: " + data.getBloodSugar());
                tvTimePeriod.setText("时段: " + data.getTimePeriod());
                tvMeasurementTime.setText("检测时间: " + data.getMeasurementTime());
            }
            super.refreshContent(e, highlight);
        }
        @Override
        public MPPointF getOffset() {
            return new MPPointF(-(getWidth() / 2f), -getHeight());
        }
    }

    public static class BloodSugarData {
        private String date;
        private float bloodSugar;
        private String timePeriod;
        private String measurementTime;

        public BloodSugarData(String date, float bloodSugar, String timePeriod, String measurementTime) {
            this.date = date;
            this.bloodSugar = bloodSugar;
            this.timePeriod = timePeriod;
            this.measurementTime = measurementTime;
        }

        public String getDate() {
            return date;
        }

        public float getBloodSugar() {
            return bloodSugar;
        }

        public String getTimePeriod() {
            return timePeriod;
        }

        public String getMeasurementTime() {
            return measurementTime;
        }
    }

    public static class BloodSugarDataSet {
        private LineDataSet lineDataSet;
        private List bloodSugarList;
        private float lowerLimitValue = 3.9f;
        private float upperLimitValue = 9.0f;

        public float getLowerLimitValue() {
            return lowerLimitValue;
        }

        public float getUpperLimitValue() {
            return upperLimitValue;
        }

        public BloodSugarDataSet(String label, int lineColor, boolean showPoints) {
            bloodSugarList = new ArrayList<>();
            lineDataSet = createLineDataSet(label, lineColor);
            setShowDataPoints(showPoints);
        }

        public void setGlucoseValueRange(float lowerLimitValue, float upperLimitValue) {
            this.lowerLimitValue = lowerLimitValue;
            this.upperLimitValue = upperLimitValue;
        }

        private LineDataSet createLineDataSet(String label, int lineColor) {
            LineDataSet set = new LineDataSet(null, label);
            set.setAxisDependency(YAxis.AxisDependency.LEFT);
            set.setColor(lineColor);
            set.setCircleColor(lineColor);
            set.setLineWidth(2f);
            set.setCircleRadius(4f);
            set.setValueTextSize(10f);
            set.setValueTextColor(Color.BLACK);
            set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
            set.setDrawFilled(true);
            set.setFillColor(lineColor);

            return set;
        }
        public void setShowDataPoints(boolean show) {
            lineDataSet.setDrawCircles(show);
            lineDataSet.setDrawValues(show);
        }
        public LineDataSet getLineDataSet() {
            return lineDataSet;
        }

        public List getBloodSugarList() {
            return bloodSugarList;
        }

        public void addData(BloodSugarData data) {
            SimpleDateFormat sdf = new SimpleDateFormat("MM/dd", Locale.getDefault());
            try {
                Date date = sdf.parse(data.getDate());
                Entry entry = new Entry(date.getTime(), data.getBloodSugar());
                entry.setData(data);
                lineDataSet.addEntry(entry);
                bloodSugarList.add(data);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }

        }

        public void addDataList(List dataList) {
            List entries = generateEntries(dataList);
            for (Entry item:entries) {
                lineDataSet.addEntry(item);
            }

            lineDataSet.setCircleColors(getCircleColors(entries));
            lineDataSet.setValueTextColors(Arrays.stream(getCircleColors(entries))
                .boxed()
                .collect(Collectors.toList()));
            bloodSugarList.addAll(dataList);
        }
        // 生成 Entry 列表
        private List generateEntries(List bloodSugarList) {
            List entries = new ArrayList<>();
            SimpleDateFormat sdf = new SimpleDateFormat("MM/dd", Locale.getDefault());
            for (int i = 0; i < bloodSugarList.size(); i++) {

                BloodSugarData data = bloodSugarList.get(i);
                try {
                    Date date = sdf.parse(data.getDate());
                    Entry entry = new Entry(i, data.getBloodSugar());
                    entry.setData(data);
                    entries.add(entry);
                } catch (ParseException e) {
                    Log.e("TAG", "generateEntries: " + e.getMessage() );
                }

            }
            return entries;
        }

        // 根据血糖值是否在范围内设置坐标点颜色
        private int[] getCircleColors(List entries) {
            int[] colors = new int[entries.size()];
            for (int i = 0; i < entries.size(); i++) {
                float glucoseValue = entries.get(i).getY();
                if (glucoseValue < lowerLimitValue) {
                    colors[i] = Color.BLUE; // 不在范围内为ajqc色
                }
                else if(glucoseValue > upperLimitValue) {
                    colors[i] = Color.RED; // 在范围内为绿色
                } else {
                    colors[i] = Color.BLACK; // 不在范围内为红色
                }
            }
            return colors;
        }
    }
}

你可能感兴趣的:(java,MPAndroidChart,LineChart)