美文网首页
android MPAndroidChart自定义markvie

android MPAndroidChart自定义markvie

作者: hao_developer | 来源:发表于2021-08-27 15:59 被阅读0次

修改前:

image.png
修改后:
image.png
MPAndroidChart https://github.com/PhilJay/MPAndroidChart

通过自定义markview来实现,重新里面重要的两个方法getOffset draw
通过draw拿到markView的宽度(\color{red}{getWidth()}\)、markView的高度(\color{red}{getHeight()}\)、折线图的宽度(\color{red}{chart.getWidth()}\)、折线图的高度(\color{red}{chart.getHeight()}\)来设置Point的偏移量

image.png

activity


import android.graphics.Color
import android.os.Bundle
import android.view.Window
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import com.alibaba.fastjson.JSON
import kotlinx.android.synthetic.main.activity_line_chart.*

/** 
 *@Description: 折线图
 */
class LineChartActivity : AppCompatActivity() {

    var entries = arrayListOf<Entry>()
    var entriestwo = arrayListOf<Entry>()
    var week = arrayListOf<String>()
    var dataSet:LineDataSet? = null
    var dataSettwo:LineDataSet? = null
    var jsonStr = "[\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-01-20 15:36:46\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-01-20 15:36:46\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 01:59:57\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 01:59:58\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 01:59:59\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 01:59:59\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 01:59:59\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:00:50\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:01:00\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:01:05\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:01:08\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:05:09\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:05:10\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:05:10\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:05:10\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:05:11\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:05:11\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"130\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:05:11\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"80\",\n" +
            "            \"dia\":\"120\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 02:06:43\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"126\",\n" +
            "            \"dia\":\"89\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 14:34:46\"\n" +
            "    },\n" +
            "    {\n" +
            "        \"testOrg\":\"智小马血压设备\",\n" +
            "        \"optionData\":{\n" +
            "            \"unit\":\"mmHg\",\n" +
            "            \"sys\":\"121\",\n" +
            "            \"dia\":\"82\"\n" +
            "        },\n" +
            "        \"cgyName\":\"血压\",\n" +
            "        \"diagnoseTime\":\"2021-07-15 14:38:56\"\n" +
            "    },\n" +
            "]"

        override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE)//去掉标题栏
        setContentView(R.layout.activity_line_chart)
        //设置数据
        initData()
        val description = chart?.getDescription()
        description?.setText("历史数据折线图"); // 设置右下角备注

        //设置颜色 及  标题
        dataSet = LineDataSet(entries, "收缩压") // 图表绑定数据,设置图表折现备注
        dataSet?.setColor(Color.parseColor("#5B8FF9")) // 设置折线图颜色
        dataSet?.setValueTextColor(Color.parseColor("#5B8FF9")) // 设置数据值的颜色
//        dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);// 设置平滑曲线
        dataSet?.setValueTextSize(12f);//设置折线图转择点的值的大小
        dataSet?.setDrawCircles(false) //设置是否绘制圆形指示器,默认true
        dataSet?.setDrawValues(false);//在点上显示数值 默认true
        dataSet?.setHighLightColor(Color.parseColor("#ABB5EA")) //折线图高亮坐标线的颜色


        //设置颜色 及  标题
        dataSettwo = LineDataSet(entriestwo, "舒张压"); // 图表绑定数据,设置图表折现备注
        dataSettwo?.setColor(Color.parseColor("#5AD8A6")); // 设置折线图颜色
        dataSettwo?.setValueTextColor(Color.parseColor("#5B8FF9")); // 设置数据值的颜色
//        dataSettwo.setMode(LineDataSet.Mode.CUBIC_BEZIER);// 设置平滑曲线
        dataSettwo?.setValueTextSize(12f);//设置折线图转择点的值的大小
        dataSettwo?.setDrawCircles(false)//设置是否绘制圆形指示器,默认true
        dataSettwo?.setDrawValues(false);//在点上显示数值 默认true
        dataSettwo?.setHighLightColor(Color.parseColor("#ABB5EA")) //折线图高亮坐标线的颜色

        //装载数据 todo
        val lineData = LineData(dataSet,dataSettwo)
//        val lineData = LineData(dataSet)
        chart.data = lineData // 图表绑定数据值

//        chart.animateXY(2000,1000)
        chart.animateX(2000)
        chart.invalidate() // 刷新图表

    }

    private fun initData() {
        val list = JSON.parseArray(jsonStr.toString(),ChartBean::class.java)
        list.forEachIndexed { index, chartBean ->
            week.add(chartBean.diagnoseTime.split(" ")[0])

            entries.add(Entry(index.toFloat(), chartBean.optionData.sys))
            entriestwo.add(Entry(index.toFloat(), chartBean.optionData.dia))
        }

        chart.setNoDataText("暂无数据")
        // 不可以缩放
        chart.setScaleEnabled(false);
        chart.setPinchZoom(false);
//        chart?.setMaxVisibleValueCount(60); //最大显示的个数。超过60个将不再显示
        //设置一页最大显示个数为6,超出部分就滑动
//        val ratio = entries.size / 18;
        chart.zoom(2.5f,1f,0f,0f);//显示的时候 是 按照多大的比率缩放显示   1f表示不放大缩小
        //是否展示网格线
        chart.setDrawGridBackground(false)
        val valueFormatter: ValueFormatter = object : ValueFormatter() {
            override fun getFormattedValue(value: Float): String {
                val index = value.toInt()
                return if (index >= 0 && index < week.size) week[index] else ""
            }
        }
        //设置markerview todo
        chart.marker = XYMarkerView(this,chart,valueFormatter,entries,entriestwo)
//        chart.marker = XYMarkerSingleView(this,chart,valueFormatter,entries)
        chart.setScaleMinima(1f,1f)
        /***折线图例 标签 设置***/
        val legend = chart.getLegend();
        legend.setForm(Legend.LegendForm.LINE);
        legend.setTextSize(11f);
        legend.setTextColor(Color.WHITE);
        //显示位置
        legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
        legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
        legend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        legend.setXEntrySpace(15f);
        legend.setYEntrySpace(15f);
        //是否绘制在图表里面
        legend.setDrawInside(false);

        //x轴设置
        val xAxis = chart.getXAxis()
        // 不显示x轴
        xAxis.setDrawAxisLine(true)
        // 设置x轴数据的位置
        xAxis.position = XAxis.XAxisPosition.BOTTOM
        xAxis.textColor = Color.WHITE
        xAxis.textSize = 6f
        xAxis.gridColor = Color.parseColor("#3E466D")
//        xAxis.setAxisMinimum(0f);
        xAxis.setGranularity(1f);//设置Y轴最小间隔
        xAxis.axisLineColor = Color.parseColor("#3E466D")
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); // 让x轴在下面
        xAxis.setGridColor(getResources().getColor(android.R.color.transparent));
        xAxis.setAvoidFirstLastClipping(true)//是否避免图表或屏幕的边缘的第一个和最后一个轴中的标签条目被裁剪
//        xAxis.setLabelRotationAngle(-30f); //对X轴进行一定角度的旋转,看着有立体效果,还能减小字体重叠
        xAxis.valueFormatter = valueFormatter

        //y轴设置
        val leftYAxis = chart.getAxisLeft();
        val rightYaxis = chart.getAxisRight();
        //保证Y轴从0开始,不然会上移一点
        leftYAxis.textColor = Color.WHITE
        leftYAxis.setDrawLabels(true)
        leftYAxis.axisMinimum = 0f
        leftYAxis.axisMaximum = 200f
        leftYAxis.axisLineColor = getResources().getColor(android.R.color.transparent)
        leftYAxis.setLabelCount(6, true)
//        leftYAxis.setEnabled(false); // 隐藏左边 的坐标轴

        rightYaxis.setEnabled(false); // 隐藏右边 的坐标轴

    }

}

自定义markview

package com.dsy.tui.line;

import android.content.Context;
import android.graphics.Canvas;
import android.widget.TextView;

import com.dsy.tui.R;
import com.github.mikephil.charting.charts.Chart;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.MarkerView;
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.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.utils.MPPointF;

import java.text.DecimalFormat;
import java.util.List;

public class XYMarkerView extends MarkerView {

    private TextView tvTime;
    private TextView tvChart;
    private TextView tvChartTwo;
    private DecimalFormat format;
    private List<Entry> entries;
    private List<Entry> entriesTwo;
    private LineChart chart;
    private IAxisValueFormatter xAxisValueFormatter;
    private Context context;

    public XYMarkerView(Context context, LineChart chart, IAxisValueFormatter xAxisValueFormatter, List<Entry> entries, List<Entry> entriesTwo) {
        super(context, R.layout.custom_marker_view);
        this.context = context;
        tvTime = (TextView) findViewById(R.id.tvTime);
        tvChart = (TextView) findViewById(R.id.tvChart);
        tvChartTwo = (TextView) findViewById(R.id.tvChartTwo);
        format = new DecimalFormat("###.0");
        this.entries = entries;
        this.xAxisValueFormatter = xAxisValueFormatter;
        this.entriesTwo = entriesTwo;
        this.chart = chart;
    }

    //回调函数每次MarkerView重绘,可以用来更新内容(用户界面)
    @Override
    public void refreshContent(Entry e, Highlight highlight) {

        LineData lineData = chart.getLineData();//得到已经绘制成型的折线图的数据
        LineDataSet set = (LineDataSet)lineData.getDataSetByIndex(0);//获取第一条折线图Y轴数据
        LineDataSet set2 = (LineDataSet)lineData.getDataSetByIndex(1);//获取第二条折线图Y轴数据
        int DataSetIndex = highlight.getDataSetIndex();//获取点击的是哪条折线上的交叉点,0就是第一条,以此类推
        int index;
        if (DataSetIndex == 0){
            index = set.getEntryIndex(e);//根据点击的该条折线的点,获取当前Y轴数据对应的index值
        }else {
            index = set2.getEntryIndex(e);//根据点击的该条折线的点,获取当前Y轴数据对应的index值
        }
        //根据index值,分别获取当前X轴上对应的两条折线的Y轴的值
        Entry entry = set.getEntryForIndex(index);
        Entry entry2 = set2.getEntryForIndex(index);

        tvTime.setText(xAxisValueFormatter.getFormattedValue(e.getX(), null));
        tvChart.setText("" + entry.getY());
        tvChartTwo.setText("" + entry2.getY());
        super.refreshContent(e, highlight);
    }

    //设置显示偏移位置
    @Override
    public MPPointF getOffset() {
        return new MPPointF((getWidth() / 8), -getHeight());
    }

    //这里修改markview偏移
    public void draw(Canvas canvas, float posX, float posY) {
        MPPointF mpPointF = new MPPointF();
        //根据项目需求通过width、height、chartWidth、chartHeight来设置point偏移位置
        float width = getWidth();//markview宽度
        float height = getHeight();//markview的高度
        float chartWidth = chart.getWidth();//chart宽度
        float chartHeight = chart.getHeight();//chart的高度
        //右边超出的情况,显示一个,隐藏一个,设置对应的偏移量
        if (chartWidth < posX + width) {
            mpPointF.x =  - (dip2px(context,10f) + getWidth());
        } else {//右边没有超出的情况,同上
            mpPointF.x = dip2px(context,10f);
        }
        //绘制方法是直接复制过来的,没动
        int saveId = canvas.save();
        // translate to the correct position and draw
        canvas.translate(posX + mpPointF.x, posY + mpPointF.y);
        draw(canvas);
        canvas.restoreToCount(saveId);
    }

    public int dip2px(Context context, float dipValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(dipValue * scale + 0.5f);
    }

}

自定义markview的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:orientation="vertical"
    android:padding="@dimen/p10"
    android:layout_height="wrap_content"
    android:background="#3D405E">

    <TextView
        android:id="@+id/tvTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:text="2020.12.24"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textColor="@android:color/white"
        android:textSize="12dp"/>

    <LinearLayout
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <View
            android:background="#5B8FF9"
            android:layout_width="@dimen/p10"
            android:layout_height="2dp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:text="收缩压"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="@android:color/white"
            android:textSize="12dp"/>

        <TextView
            android:id="@+id/tvChart"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="35dp"
            android:text="0.00"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="@android:color/white"
            android:textSize="12dp"/>

    </LinearLayout>

    <LinearLayout
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <View
            android:background="#5AD8A6"
            android:layout_width="@dimen/p10"
            android:layout_height="2dp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:text="舒张压"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="@android:color/white"
            android:textSize="12dp"/>

        <TextView
            android:id="@+id/tvChartTwo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="35dp"
            android:text="0.00"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="@android:color/white"
            android:textSize="12dp"/>

    </LinearLayout>

</LinearLayout>

主布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/shape_rect_gradient_262949_to_100f19"
    android:orientation="vertical">

    <com.github.mikephil.charting.charts.LineChart
        android:id="@+id/chart"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

设置均值线

image.png

设置代码如下

//均值线
val avgLine = LimitLine(100f)
avgLine.enableDashedLine(5.0f, 3.0f, 3.0f)
avgLine.lineColor = Color.parseColor("#33CC33")
leftYAxis.addLimitLine(avgLine)

相关文章

网友评论

      本文标题:android MPAndroidChart自定义markvie

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