MPAndroidChart-为顶部和底部轴绘制不同的标签

时间:2018-10-17 10:22:43

标签: android mpandroidchart

我想为顶部和底部xAxis使用不同的值格式器,以实现类似于以下的效果:

enter image description here

1 个答案:

答案 0 :(得分:0)

由于无法在StackOverflow上找到解决方案,我决定发布自己的解决方案。

为此,我们必须提供XAxisRenderer的自定义实现:

class DoubleXLabelAxisRenderer(
        viewPortHandler: ViewPortHandler,
        xAxis: XAxis,
        transformer: Transformer,
        private val topValueFormatter: IAxisValueFormatter) : XAxisRenderer(viewPortHandler, xAxis, transformer) {

    override fun renderAxisLabels(c: Canvas) {
        if (!mXAxis.isEnabled || !mXAxis.isDrawLabelsEnabled)
            return

        val yoffset = mXAxis.yOffset

        mAxisLabelPaint.typeface = mXAxis.typeface
        mAxisLabelPaint.textSize = mXAxis.textSize
        mAxisLabelPaint.color = mXAxis.textColor

        val pointF = MPPointF.getInstance(0f, 0f)
        if (mXAxis.position == XAxis.XAxisPosition.TOP) {
            pointF.x = 0.5f
            pointF.y = 1.0f
            drawLabels(c, mViewPortHandler.contentTop() - yoffset, pointF)

        } else if (mXAxis.position == XAxis.XAxisPosition.TOP_INSIDE) {
            pointF.x = 0.5f
            pointF.y = 1.0f
            drawLabels(c, mViewPortHandler.contentTop() + yoffset + mXAxis.mLabelRotatedHeight.toFloat(), pointF)

        } else if (mXAxis.position == XAxis.XAxisPosition.BOTTOM) {
            pointF.x = 0.5f
            pointF.y = 0.0f
            drawLabels(c, mViewPortHandler.contentBottom() + yoffset, pointF)

        } else if (mXAxis.position == XAxis.XAxisPosition.BOTTOM_INSIDE) {
            pointF.x = 0.5f
            pointF.y = 0.0f
            drawLabels(c, mViewPortHandler.contentBottom() - yoffset - mXAxis.mLabelRotatedHeight.toFloat(), pointF)

        } else { // BOTH SIDED
            pointF.x = 0.5f
            pointF.y = 1.0f
            drawLabelsTop(c, mViewPortHandler.contentTop() - yoffset, pointF)
            pointF.x = 0.5f
            pointF.y = 0.0f
            drawLabels(c, mViewPortHandler.contentBottom() + yoffset, pointF)
        }
        MPPointF.recycleInstance(pointF)
    }

    private fun drawLabelsTop(c: Canvas, pos: Float, anchor: MPPointF) {

        val labelRotationAngleDegrees = mXAxis.labelRotationAngle
        val centeringEnabled = mXAxis.isCenterAxisLabelsEnabled

        val positions = FloatArray(mXAxis.mEntryCount * 2)


        for(i in 0 until positions.size step 2) {
            if (centeringEnabled) {
                positions[i] = mXAxis.mCenteredEntries[i / 2]
            } else {
                positions[i] = mXAxis.mEntries[i / 2]
            }
        }

        mTrans.pointValuesToPixel(positions)

        for(i in 0 until positions.size step 2) {
            var x = positions[i]

            if (mViewPortHandler.isInBoundsX(x)) {

                val label = topValueFormatter.getFormattedValue(mXAxis.mEntries[i / 2], mXAxis)

                if (mXAxis.isAvoidFirstLastClippingEnabled) {

                    if (i == mXAxis.mEntryCount - 1 && mXAxis.mEntryCount > 1) {
                        val width = Utils.calcTextWidth(mAxisLabelPaint, label).toFloat()

                        if (width > mViewPortHandler.offsetRight() * 2 && x + width > mViewPortHandler.chartWidth)
                            x -= width / 2

                    } else if (i == 0) {

                        val width = Utils.calcTextWidth(mAxisLabelPaint, label).toFloat()
                        x += width / 2
                    }
                }

                drawLabel(c, label, x, pos, anchor, labelRotationAngleDegrees)
            }
        }
    }
}

然后将其设置在我们的图表上:

chart.setXAxisRenderer(
    DoubleXLabelAxisRenderer(
        chart.viewPortHandler, 
        chart.xAxis, 
        chart.getTransformer(YAxis.AxisDependency.LEFT), 
        IAxisValueFormatter { value, axis -> "someCustomValueForTopLabel" }))

当然,或者xAxis的位置都应该设置在两侧:

chart.xAxis.position = XAxis.XAxisPosition.BOTH_SIDED

我希望遇到这个问题的人能找到答案

相关问题