Reputation: 829
I would like to place an arrow at the end of the axis, but I don't know how to achieve this in MPAndroidCharts library. It should look like this at the end.
My current styling:
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)
Upvotes: 3
Views: 385
Reputation: 9113
To add an arrow on the end of X and Y axis you have to make a custom XAxisRenderer
and YAxisRenderer
. All you have to do is to make a subclass for each renderer and override the public method renderAxisLine(c: Canvas)
which is responsible to draw the axis line and modify the code of base class by adding also the arrow icon at the end of each axis line. An example is like the below:
For 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)
}
}
}
For 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)
}
}
}
In the above samples i have used the below vector drawables where you can change based on your needs:
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>
Usage for X axis:
chart.setXAxisRenderer(ArrowXAxisRenderer(this, chart.getViewPortHandler(), chart.getXAxis(), chart.getTransformer(YAxis.AxisDependency.LEFT)))
Usage for Y (Left or Right) axis:
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)))
Result:
Note: This was tested with 'com.github.PhilJay:MPAndroidChart:v3.1.0'
Upvotes: 4
Reputation: 689
I have checked the documentation and it seems that there is no option to render an arrow or something else on the end of one of the axis.
Maybe you can create an overlay for your chart, but i guess placing the arrows on the correct place is not a good idea.
Upvotes: 0