MPAndroidChart多条折线

1.引入依赖

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

2.需求效果图

3.

设置Linechart数据

    private fun initLineChart(list: List<HourStatistics>) {
        mLinechart.description.isEnabled = false
        mLinechart.legend.direction = Legend.LegendDirection.LEFT_TO_RIGHT
        mLinechart.legend.orientation = Legend.LegendOrientation.HORIZONTAL
        mLinechart.legend.verticalAlignment = Legend.LegendVerticalAlignment.TOP
        mLinechart.setTouchEnabled(true)
        mLinechart.setDrawGridBackground(false)
        // enable scaling and dragging
        mLinechart.isDragEnabled = false
        mLinechart.setScaleEnabled(false)
        // chart.setScaleXEnabled(true);
        // chart.setScaleYEnabled(true);
        // force pinch zoom along both axis
        mLinechart.setPinchZoom(false)
        // // Y-Axis Style // //
        val yAxis: YAxis = mLinechart.axisLeft
        // disable dual axis (only use LEFT axis)
        mLinechart.axisRight.isEnabled = false
        yAxis.setDrawLimitLinesBehindData(true)
        yAxis.setDrawZeroLine(false)

        /**
         * 绘制虚线网格线,
         * DashPathEffect:
         * @params:new float[]{30,20,30,20}   先绘制30px实线,再绘制20px透明,再绘制30px实线,再绘制20px透明
         * @params:0  偏移量,若为20,则效果为:先绘制10px实线,再绘制20px透明,再绘制30px实线,再绘制20px透明
         */
        yAxis.setGridDashedLine(DashPathEffect(floatArrayOf(30f, 20f, 30f, 20f), 0F))

        mLinechart.axisLeft.setDrawLabels(true)
        mLinechart.axisLeft.setDrawTopYLabelEntry(true)
        mLinechart.axisLeft.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART)

        var minY= list[0].menCountByHour
        var maxY=0
        list.forEach {
                var maleEntry=Entry()
                maleEntry.x= it.reportHour.toFloat()
                maleEntry.y=it.menCountByHour.toFloat()

                var femaleEntry=Entry()
                femaleEntry.x= it.reportHour.toFloat()
                femaleEntry.y=it.womanCountByHour.toFloat()

                xDataMale.add(maleEntry)
                xDatasFemale.add(femaleEntry)
                //获取最小值
                if(it.menCountByHour<minY || it.womanCountByHour<minY){
                    if (it.menCountByHour<it.womanCountByHour){
                        minY = it.menCountByHour
                    }else if (it.menCountByHour>it.womanCountByHour){
                        minY = it.womanCountByHour
                    }else{
                        minY = it.menCountByHour
                    }
                }
                //获取最大值
                if(it.menCountByHour> maxY || it.womanCountByHour> maxY){
                      if (it.menCountByHour>it.womanCountByHour){
                          maxY=it.menCountByHour
                      }else if (it.menCountByHour<it.womanCountByHour){
                          maxY=it.womanCountByHour
                      }else{
                          maxY=it.menCountByHour
                      }
                }

        }

        yAxis.axisMinimum = (minY/10 *10).toFloat() //设置Y轴最小值

        yAxis.axisMaximum = (((maxY/10)+1)*10).toFloat() //设置Y轴最大值

        yAxis.labelCount = 10 //设置Y轴标签数

        yAxis.granularity = (yAxis.axisMaximum-yAxis.axisMinimum)/10 //设置Y轴标签单位间隔

        val xAxis: XAxis = mLinechart.xAxis // 获取X轴

        xAxis.position = XAxis.XAxisPosition.BOTTOM // X轴绘制位置,默认是顶部

        xAxis.setDrawGridLines(false) //不绘制x轴格网线

        //x坐标轴设置  下面几个属性很重要
        xAxis.axisMinimum = 0f //设置x轴最小值

        xAxis.axisMaximum = 24f //设置x轴最大值

        xAxis.labelCount = 11 //设置x轴显示的标签个数

        xAxis.granularity = 2f //设置最小间隔,

        xAxis.axisLineWidth = 1f //设置x轴宽度, ...其他样式、

        xAxis.setDrawLabels(true)
        xAxis.setCenterAxisLabels(false) //x轴居中显示

        xAxis.valueFormatter = object : ValueFormatter() {
            override fun getFormattedValue(value: Float): String {
                if (value==24.0f){
                    return ""
                }else{
                    return value.toInt().toString()
                }
            }
        }
        //y轴设置
        yAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART) //y轴标签绘制的位置

        yAxis.setDrawGridLines(true) // 显示Y轴网格线

        yAxis.gridColor = Color.BLACK // 线条颜色

        yAxis.gridLineWidth = 1f // 线条宽度

        yAxis.enableGridDashedLine(10f, 10f, 0f) // 线条为虚线

        yAxis.valueFormatter = object : ValueFormatter() {
            override fun getFormattedValue(value: Float): String {
                return if (value > 0 ) {
                     value.toInt().toString()
                } else {
                    ""
                }
            }
        }

        val dataSets1: LineDataSet
        val dataSets2: LineDataSet
        //设置数据
        if (mLinechart.data != null && mLinechart.data.dataSetCount > 0) {
            dataSets1 = mLinechart.data.getDataSetByIndex(0) as LineDataSet
            dataSets1.values = xDataMale

            dataSets2 = mLinechart.data.getDataSetByIndex(1) as LineDataSet
            dataSets2.values = xDatasFemale
            mLinechart.data.notifyDataChanged()
            mLinechart.notifyDataSetChanged()
        } else {
            //创建一个数据集,并给它一个类型
            dataSets1 = LineDataSet(xDataMale, "男厕客流量" )
            dataSets1.setDrawCircles(false)      //不绘制圆点
            dataSets1.setDrawCircleHole(true)    //是否实心
            dataSets1.setDrawValues(false)       //是否显示Y轴的值
            dataSets1.color = resources.getColor(R.color.main_color)
            dataSets1.lineWidth = 1f
            dataSets1.setCircleColor(resources.getColor(R.color.main_color))
            dataSets1.valueTextSize = 13f
            dataSets1.valueTextColor = resources.getColor(R.color.main_color)
            dataSets1.mode = LineDataSet.Mode.CUBIC_BEZIER
            dataSets1.fillColor = resources.getColor(R.color.main_color)  // 设置区域内填充颜色
            dataSets1.fillAlpha = 100 // 设置区域内填充颜色的透明度
            dataSets1.setDrawFilled(true)
            // 设置 FillFormatter 来定义填充区域的样式
            dataSets1.fillFormatter = object : DefaultFillFormatter() {
                override fun getFillLinePosition(dataSet: ILineDataSet, dataProvider: LineDataProvider): Float {
                    return mLinechart.axisLeft.axisMinimum // 设置填充区域的底部位置
                }
            }

            dataSets2 = LineDataSet(xDatasFemale, "女厕客流量" )
            dataSets2.setDrawCircles(false)   //不绘制圆点
            dataSets2.setDrawCircleHole(true)    //是否实心
            dataSets2.setDrawValues(false)      //是否显示Y轴的值
            dataSets2.color = resources.getColor(R.color.color_4CAF50)
            dataSets2.lineWidth = 1f
            dataSets2.setCircleColor(resources.getColor(R.color.color_4CAF50))
            dataSets2.valueTextSize = 13f
            dataSets2.valueTextColor = resources.getColor(R.color.color_4CAF50)
            dataSets2.mode = LineDataSet.Mode.CUBIC_BEZIER
            dataSets2.fillColor = resources.getColor(R.color.color_4CAF50)  // 设置区域内填充颜色
            dataSets2.fillAlpha = 100 // 设置区域内填充颜色的透明度
            dataSets2.setDrawFilled(true)
            dataSets2.fillFormatter = object : DefaultFillFormatter() {
                override fun getFillLinePosition(dataSet: ILineDataSet, dataProvider: LineDataProvider): Float {
                    return mLinechart.axisLeft.axisMinimum // 设置填充区域的底部位置
                }
            }
            //创建一个数据集的数据对象
            val data = LineData(dataSets1,dataSets2)
            //设置数据
            mLinechart.data = data

            val mv = CustomMarkerView(mLinechart,requireActivity(),R.layout.custom_marker_linechart);
            mLinechart.marker = mv
            mLinechart.setOnChartValueSelectedListener(object :OnChartValueSelectedListener{
                override fun onValueSelected(e: Entry?, h: Highlight?) {}

                override fun onNothingSelected() {}
            })

        }

        mLinechart.invalidate()
    }

   创建MarkerView

    // 创建一个 MarkerView 类来自定义显示选中点数值的视图
    class CustomMarkerView(lineChartView: LineChart,context: Context?, layoutResource: Int) : MarkerView(context, layoutResource) {
        private val tv_1: TextView
        private val tv_2: TextView
        private val tv_3: TextView
        private var chartView: LineChart

        // 在绘制 MarkerView 时回调,可以在此方法中设置显示的内容
        override fun refreshContent(entry: Entry, highlight: Highlight) {
            val xValue =entry.x      // 获取所选点的X轴值
            val dataSets:List<ILineDataSet> = chartView.lineData.dataSets
            val yValue0= dataSets[0].getEntryForXValue(xValue,Float.NaN)
            val yValue1= dataSets[1].getEntryForXValue(xValue,Float.NaN)
            tv_1.text="${xValue.toInt()}点"
            tv_2.text="${yValue0.y.toInt()}"
            tv_3.text="${yValue1.y.toInt()}"
            // 获取所有数据集
            super.refreshContent(entry, highlight)
        }

        // 在 MarkerView 位置发生改变时回调,可以在此方法中调整位置
        fun markerPositionChanged(marker: Marker?) {
            // 自定义调整位置逻辑
        }

        override fun getOffset(): MPPointF? { //调整MarkerView位置   
            return MPPointF((-(width / 2)-60).toFloat(), (-height - 30).toFloat())
        }

        init {
            tv_1 = findViewById(R.id.tv_1)
            tv_2 = findViewById(R.id.tv_2)
            tv_3 = findViewById(R.id.tv_3)
            chartView=lineChartView
        }
    }

实体类

data class HourStatistics(
    @Expose
    var menCountByHour: Int,
    @Expose
    val reportHour: Int,
    @Expose
    var womanCountByHour: Int
)

MarkerView布局 custom_marker_linechart

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/shape_rec_c5all"
    android:paddingHorizontal="10dp"
    android:paddingVertical="5dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="13sp"
        android:text="0点"/>

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_marginVertical="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <View
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:background="@color/main_color"/>

        <TextView
            android:layout_marginLeft="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="13sp"
            android:text="男厕客流量:"/>

        <TextView
            android:id="@+id/tv_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:textSize="13sp"
            android:text="0"/>
    </androidx.appcompat.widget.LinearLayoutCompat>


    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <View
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:background="@color/color_4CAF50"/>

        <TextView
            android:layout_marginLeft="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="13sp"
            android:text="女厕客流量:"/>

        <TextView
            android:id="@+id/tv_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:textSize="13sp"
            android:text="0"/>
    </androidx.appcompat.widget.LinearLayoutCompat>

</androidx.appcompat.widget.LinearLayoutCompat>

效果图

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值