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 轴的末端添加箭头,您必须自定义 XAxisRenderer
和 YAxisRenderer
。你所要做的就是为每个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'
测试的
我想在轴的末端放置一个箭头,但我不知道如何在 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 轴的末端添加箭头,您必须自定义 XAxisRenderer
和 YAxisRenderer
。你所要做的就是为每个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'
测试的