Im having trouble with clipping x axis labels. The problem can be seen in the picture
What I would like to change is that instead of the labels ending at that place, that they instead start at that place so the whole text can be seen. code that im using:
barChart.axisLeft.isEnabled = false
barChart.setTouchEnabled(false)
barChart.isDragEnabled = false
barChart.description = null
barChart.xAxis.setDrawGridLines(false)
barChart.xAxis.setCenterAxisLabels(true)
barChart.xAxis.valueFormatter = IndexAxisValueFormatter(nameArray)
barChart.xAxis.position = XAxis.XAxisPosition.BOTTOM_INSIDE
barChart.xAxis.textColor = Color.WHITE
barChart.axisRight.textColor = Color.WHITE
barChart.legend.textColor = Color.WHITE
Thanks in advance :)
The axis labels on a bar chart can be difficult to position properly, so for something like this it's often easier to use a custom renderer for the dataset values instead. To do this, you can create a custom renderer that reads the label you want from the BarEntry
data field and draws it where you want relative to the bar position.
The renderer below is a simplified copy of the base HorizontalBarChartRenderer
that overrides the drawValues
method.
class MyRenderer(
chart: HorizontalBarChart
) : HorizontalBarChartRenderer(chart, chart.animator, chart.viewPortHandler) {
override fun drawValues(c: Canvas?) {
val dataSets = mChart.barData.dataSets
val valueOffsetPlus = Utils.convertDpToPixel(5f)
dataSets.forEachIndexed { i, ds ->
applyValueTextStyle(ds)
val buffer = mBarBuffers[i]
val maxJ = ceil(buffer.buffer.size*mAnimator.phaseX).toInt()
for(j in 0 until maxJ step 4) {
if( !mViewPortHandler.isInBoundsTop(buffer.buffer[j+1]))
break
if( !mViewPortHandler.isInBoundsX(buffer.buffer[j]))
continue
if( !mViewPortHandler.isInBoundsBottom(buffer.buffer[j+1]))
continue
// Read the label from the BarEntry data field
val entry = ds.getEntryForIndex(j / 4)
val formattedValue = (entry.data as? String).orEmpty()
// Modify the x, y position here to control where the
// text is. The "buffer" array gives the positions of
// the current bar (in pixels from top left corner)
drawValue(c,
formattedValue,
buffer.buffer[j] + valueOffsetPlus,
buffer.buffer[j+1] + ds.valueTextSize,
ds.getValueTextColor(j / 2));
}
}
}
}
Once you have defined a custom renderer, you add it to the chart with your list of labels, and turn off the regular axis labels, like this:
// set the custom renderer for the chart
barChart.renderer = MyRenderer(barChart)
// turn off labels on x axis
barChart.xAxis.setDrawLabels(false)
For this example, I'm using the following data set
val entries1 = listOf(BarEntry(0f,3f,"Lorem"))
val dataset1 = BarDataSet(entries1, "Foo").apply { color = Color.GREEN }
val entries2 = listOf(
BarEntry(1f,4f,"Ipsum"),
BarEntry(2f,5f,"Dolorum")
)
val dataset2 = BarDataSet(entries2, "Bar").apply { color = Color.LTGRAY }
val entries3 = listOf(BarEntry(3f,6f,"Pescotum"))
val dataset3 = BarDataSet(entries3, "Baz").apply { color = Color.CYAN }
val sets = listOf(dataset1, dataset2, dataset3)
sets.forEach { it.valueTextSize = 12f }
barChart.data = BarData(sets)
You can also check out this solution for a version (in Java) that draws the labels outside the bars.