android - MPAndroidChart - 饼图 - 自定义标签线

标签 android pie-chart mpandroidchart

我正在尝试使用带有饼图的 MPAndroidChart 绘制标签线,如图所示。我不知道怎么做

  • 将线与图表分离
  • 在线的开头画那个小圆圈。

  • enter image description here

    谢谢你。

    最佳答案

    这绝非易事。要将线条与图表分离,您可以使用 valueLinePart1OffsetPercentage和玩线部分的长度。但是要让图表在行尾绘制点,您需要一个自定义渲染器。这是一个:

    class CustomPieChartRenderer(pieChart: PieChart, val circleRadius: Float)
        : PieChartRenderer(pieChart, pieChart.animator, pieChart.viewPortHandler) {
    
        override fun drawValues(c: Canvas) {
            super.drawValues(c)
    
            val center = mChart.centerCircleBox
    
            val radius = mChart.radius
            var rotationAngle = mChart.rotationAngle
            val drawAngles = mChart.drawAngles
            val absoluteAngles = mChart.absoluteAngles
    
            val phaseX = mAnimator.phaseX
            val phaseY = mAnimator.phaseY
    
            val roundedRadius = (radius - radius * mChart.holeRadius / 100f) / 2f
            val holeRadiusPercent = mChart.holeRadius / 100f
            var labelRadiusOffset = radius / 10f * 3.6f
    
            if (mChart.isDrawHoleEnabled) {
                labelRadiusOffset = (radius - radius * holeRadiusPercent) / 2f
                if (!mChart.isDrawSlicesUnderHoleEnabled && mChart.isDrawRoundedSlicesEnabled) {
                    rotationAngle += roundedRadius * 360 / (Math.PI * 2 * radius).toFloat()
                }
            }
    
            val labelRadius = radius - labelRadiusOffset
    
            val dataSets = mChart.data.dataSets
    
            var angle: Float
            var xIndex = 0
    
            c.save()
            for (i in dataSets.indices) {
                val dataSet = dataSets[i]
                val sliceSpace = getSliceSpace(dataSet)
                for (j in 0 until dataSet.entryCount) {
                    angle = if (xIndex == 0) 0f else absoluteAngles[xIndex - 1] * phaseX
                    val sliceAngle = drawAngles[xIndex]
                    val sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * labelRadius)
                    angle += (sliceAngle - sliceSpaceMiddleAngle / 2f) / 2f
    
                    if (dataSet.valueLineColor != ColorTemplate.COLOR_NONE) {
                        val transformedAngle = rotationAngle + angle * phaseY
                        val sliceXBase = cos(transformedAngle * Utils.FDEG2RAD.toDouble()).toFloat()
                        val sliceYBase = sin(transformedAngle * Utils.FDEG2RAD.toDouble()).toFloat()
                        val valueLinePart1OffsetPercentage = dataSet.valueLinePart1OffsetPercentage / 100f
                        val line1Radius = if (mChart.isDrawHoleEnabled) {
                            (radius - radius * holeRadiusPercent) * valueLinePart1OffsetPercentage + radius * holeRadiusPercent
                        } else {
                            radius * valueLinePart1OffsetPercentage
                        }
                        val px = line1Radius * sliceXBase + center.x
                        val py = line1Radius * sliceYBase + center.y
    
                        if (dataSet.isUsingSliceColorAsValueLineColor) {
                            mRenderPaint.color = dataSet.getColor(j)
                        }
                        c.drawCircle(px, py, circleRadius, mRenderPaint)
                    }
    
                    xIndex++
                }
            }
            MPPointF.recycleInstance(center)
            c.restore()
        }
    }
    

    此自定义渲染器扩展了默认的饼图渲染器。我基本上只是从 PieChartRenderer.drawValues 复制代码方法,将其转换为 Kotlin,并删除所有不需要的内容。我只保留了确定行尾点位置所需的逻辑。

    我试图重现您展示的图像:

    
    val chart: PieChart = view.findViewById(R.id.pie_chart)
    chart.setExtraOffsets(40f, 0f, 40f, 0f)
    
    // Custom renderer used to add dots at the end of value lines.
    chart.renderer = CustomPieChartRenderer(chart, 10f)
    
    val dataSet = PieDataSet(listOf(
            PieEntry(40f),
            PieEntry(10f),
            PieEntry(10f),
            PieEntry(15f),
            PieEntry(10f),
            PieEntry(5f),
            PieEntry(5f),
            PieEntry(5f)
    ), "Pie chart")
    
    // Chart colors
    val colors = listOf(
            Color.parseColor("#4777c0"),
            Color.parseColor("#a374c6"),
            Color.parseColor("#4fb3e8"),
            Color.parseColor("#99cf43"),
            Color.parseColor("#fdc135"),
            Color.parseColor("#fd9a47"),
            Color.parseColor("#eb6e7a"),
            Color.parseColor("#6785c2"))
    dataSet.colors = colors
    dataSet.setValueTextColors(colors)
    
    // Value lines
    dataSet.valueLinePart1Length = 0.6f
    dataSet.valueLinePart2Length = 0.3f
    dataSet.valueLineWidth = 2f
    dataSet.valueLinePart1OffsetPercentage = 115f  // Line starts outside of chart
    dataSet.isUsingSliceColorAsValueLineColor = true
    
    // Value text appearance
    dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE
    dataSet.valueTextSize = 16f
    dataSet.valueTypeface = Typeface.DEFAULT_BOLD
    
    // Value formatting
    dataSet.valueFormatter = object : ValueFormatter() {
        private val formatter = NumberFormat.getPercentInstance()
    
        override fun getFormattedValue(value: Float) =
                formatter.format(value / 100f)
    }
    chart.setUsePercentValues(true)
    
    dataSet.selectionShift = 3f
    
    // Hole
    chart.isDrawHoleEnabled = true
    chart.holeRadius = 50f
    
    // Center text
    chart.setDrawCenterText(true)
    chart.setCenterTextSize(20f)
    chart.setCenterTextTypeface(Typeface.DEFAULT_BOLD)
    chart.setCenterTextColor(Color.parseColor("#222222"))
    chart.centerText = "Center\ntext"
    
    // Disable legend & description
    chart.legend.isEnabled = false
    chart.description = null
    
    chart.data = PieData(dataSet)
    

    同样,不是很简单。我希望你喜欢 Kotlin!如果您经常需要,您可以将大部分配置代码移动到子类中。结果如下:

    enter image description here

    我不是 MPAndroidChart 专家。事实上,我只用过一次,那是两年前的事了。但是,如果您进行研究,则大多数时候都可以找到解决方案。幸运的是,MPAndroidChart 是一个非常可定制的。

    关于android - MPAndroidChart - 饼图 - 自定义标签线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60906962/

    相关文章:

    android - Loader<Cursor> 只加载选定的行+下一行

    java - 寻找 Rxjava 运算符将源合并到一个流中

    java - 从另一个 Activity 引用一个 Activity 的属性

    Python matplotlib - 如何创建用颜色代表频率的饼图?

    html - 重叠 div 上的悬停事件不起作用

    android - MPChartAndroid : how to interact with a BarDataSet that has a missing Entry?

    mpandroidchart - ios-charts 设置数据后如何失效/重绘

    ArrayList 和 RecyclerView 的 java.lang.OutOfMemoryError

    MPAndroidChart - 更改消息 "No chart data available"

    google-visualization - 如何在 Google Chart 中隐藏标签?