MpAndroidChart:将箭头添加到轴的末端

MpAndroidChart: Add an Arrow to the End of an Axis

我想在轴的末端放置一个箭头,但我不知道如何在 MPAndroidCharts 库中实现它。最后应该是这样的。

我目前的造型:

  val xAxis = chart.xAxis
  xAxis.setDrawLabels(false)
  xAxis.setDrawAxisLine(true)
  xAxis.setDrawGridLines(false)
  xAxis.position = XAxis.XAxisPosition.BOTTOM
  xAxis.axisLineWidth = 1.5f

  val axisLeft = chart.axisLeft
  axisLeft.setDrawGridLines(false)
  axisLeft.setDrawZeroLine(false)
  axisLeft.setDrawLabels(false)
  axisLeft.axisLineWidth = 1.5f
  axisLeft.setDrawTopYLabelEntry(true)

  val axisRight = chart.axisRight
  axisRight.setDrawGridLines(false)
  axisRight.setDrawLabels(false)
  axisRight.setDrawZeroLine(false)
  axisRight.setDrawAxisLine(false)

我检查了 documentation,似乎没有选项可以在其中一个轴的末端渲染箭头或其他东西。

或许您可以为您的图表创建一个叠加层,但我想将箭头放在正确的位置并不是一个好主意。

要在 X 轴和 Y 轴的末端添加箭头,您必须自定义 XAxisRendererYAxisRenderer。你所要做的就是为每个renderer做一个subclass并重写负责绘制轴线的public方法renderAxisLine(c: Canvas)和修改baseclass的代码] 通过在每条轴线的末尾添加箭头图标。示例如下:

对于 ArrowXAxisRenderer:

class ArrowXAxisRenderer(context: Context, viewPortHandler: ViewPortHandler?, xAxis: XAxis?, trans: Transformer?)
    : XAxisRenderer(viewPortHandler, xAxis, trans) {

    private val arrowRightIcon: Drawable?
    private val arrowWidth: Int
    private val arrowHeight: Int

    init {
        arrowRightIcon = ContextCompat.getDrawable(context, R.drawable.ic_arrow_right)
        arrowWidth = arrowRightIcon!!.intrinsicWidth
        arrowHeight = arrowRightIcon.intrinsicHeight
    }

    override fun renderAxisLine(c: Canvas) {

        if (!mXAxis.isDrawAxisLineEnabled || !mXAxis.isEnabled) return

        mAxisLinePaint.color = mXAxis.axisLineColor
        mAxisLinePaint.strokeWidth = mXAxis.axisLineWidth
        mAxisLinePaint.pathEffect = mXAxis.axisLineDashPathEffect

        if (mXAxis.position == XAxis.XAxisPosition.TOP ||
            mXAxis.position == XAxis.XAxisPosition.TOP_INSIDE ||
            mXAxis.position == XAxis.XAxisPosition.BOTH_SIDED) {

            //draw the top X axis line
            c.drawLine(
                mViewPortHandler.contentLeft(),
                mViewPortHandler.contentTop(),
                mViewPortHandler.contentRight(),
                mViewPortHandler.contentTop(),
                mAxisLinePaint
            )

            //draw the arrowRightIcon on the right side of top X axis
            arrowRightIcon!!.bounds =
                Rect(
                    mViewPortHandler.contentRight().toInt() - arrowWidth / 2,
                    mViewPortHandler.contentTop().toInt() - arrowHeight / 2,
                    mViewPortHandler.contentRight().toInt() + arrowWidth / 2,
                    mViewPortHandler.contentTop().toInt() + arrowHeight / 2
                )
            arrowRightIcon.draw(c)
        }

        if (mXAxis.position == XAxis.XAxisPosition.BOTTOM ||
            mXAxis.position == XAxis.XAxisPosition.BOTTOM_INSIDE ||
            mXAxis.position == XAxis.XAxisPosition.BOTH_SIDED) {

            //draw the bottom X axis line
            c.drawLine(
                mViewPortHandler.contentLeft(),
                mViewPortHandler.contentBottom(),
                mViewPortHandler.contentRight(),
                mViewPortHandler.contentBottom(),
                mAxisLinePaint
            )

            //draw the arrowRightIcon on the right side of bottom X axis
            arrowRightIcon!!.bounds =
                Rect(
                    mViewPortHandler.contentRight().toInt() - arrowWidth / 2,
                    mViewPortHandler.contentBottom().toInt() - arrowHeight / 2,
                    mViewPortHandler.contentRight().toInt() + arrowWidth / 2,
                    mViewPortHandler.contentBottom().toInt() + arrowHeight / 2
                )
            arrowRightIcon.draw(c)
        }
    }
}

对于 ArrowYAxisRenderer:

class ArrowYAxisRenderer(context: Context, viewPortHandler: ViewPortHandler?, yAxis: YAxis?, trans: Transformer?)
    : YAxisRenderer(viewPortHandler, yAxis, trans) {

    private val arrowUpIcon: Drawable?
    private val arrowWidth: Int
    private val arrowHeight: Int

    init {
        arrowUpIcon = ContextCompat.getDrawable(context, R.drawable.ic_arrow_up)
        arrowWidth = arrowUpIcon!!.intrinsicWidth
        arrowHeight = arrowUpIcon.intrinsicHeight
    }

    override fun renderAxisLine(c: Canvas) {

        if (!mYAxis.isEnabled || !mYAxis.isDrawAxisLineEnabled) return

        mAxisLinePaint.color = mYAxis.axisLineColor
        mAxisLinePaint.strokeWidth = mYAxis.axisLineWidth

        if (mYAxis.axisDependency == YAxis.AxisDependency.LEFT) {

            //draw the left Y line axis
            c.drawLine(
                mViewPortHandler.contentLeft(),
                mViewPortHandler.contentTop(),
                mViewPortHandler.contentLeft(),
                mViewPortHandler.contentBottom(),
                mAxisLinePaint
            )

            //draw the arrowUp on top of the left Y axis
            arrowUpIcon!!.bounds =
                Rect(mViewPortHandler.contentLeft().toInt() - arrowWidth / 2,
                    mViewPortHandler.contentTop().toInt() - arrowHeight / 2,
                    mViewPortHandler.contentLeft().toInt() + arrowWidth / 2,
                    mViewPortHandler.contentTop().toInt() + arrowHeight / 2
                )
            arrowUpIcon.draw(c)
        }
        else {

            //draw the right Y line axis
            c.drawLine(
                mViewPortHandler.contentRight(),
                mViewPortHandler.contentTop(),
                mViewPortHandler.contentRight(),
                mViewPortHandler.contentBottom(),
                mAxisLinePaint
            )

            //draw the arrowUp on top of the right Y axis
            arrowUpIcon!!.bounds =
                Rect(
                    mViewPortHandler.contentRight().toInt() - arrowWidth / 2,
                    mViewPortHandler.contentTop().toInt() - arrowHeight / 2,
                    mViewPortHandler.contentRight().toInt() + arrowWidth / 2,
                    mViewPortHandler.contentTop().toInt() + arrowHeight / 2
                )
            arrowUpIcon.draw(c)
        }
    }
}

在上面的示例中,我使用了下面的矢量绘图,您可以根据自己的需要进行更改:

R.drawable.ic_arrow_right:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="@android:color/darker_gray">
    <path
        android:fillColor="@android:color/darker_gray"
        android:pathData="M8.59,16.59L13.17,12 8.59,7.41 10,6l6,6 -6,6 -1.41,-1.41z"/>
</vector>

R.drawable.ic_arrow_up:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="@android:color/darker_gray">
    <path
        android:fillColor="@android:color/darker_gray"
        android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
</vector>

X轴用法:

chart.setXAxisRenderer(ArrowXAxisRenderer(this, chart.getViewPortHandler(), chart.getXAxis(), chart.getTransformer(YAxis.AxisDependency.LEFT)))

Y(左或右)轴的用法:

chart.setRendererLeftYAxis(ArrowYAxisRenderer(this, chart.getViewPortHandler(), chart.getAxisLeft(), chart.getTransformer(YAxis.AxisDependency.LEFT)))
chart.setRendererRightYAxis(ArrowYAxisRenderer(this, chart.getViewPortHandler(), chart.getAxisRight(), chart.getTransformer(YAxis.AxisDependency.RIGHT)))

结果:

注意: 这是用 'com.github.PhilJay:MPAndroidChart:v3.1.0'

测试的