-
-
Notifications
You must be signed in to change notification settings - Fork 9.1k
Description
Hello, I'm using MPAndroidChart with a RecyclerView to display a dynamic graph. I'm trying to control the number of visible X-axis labels by using the setVisibleXRangeMaximum and setVisibleXRangeMinimum methods, but I’m encountering an issue where only 6 X-axis labels are showing up, regardless of the range settings.
Here’s what I’ve tried so far:
I have a dataset with more than 6 entries.
I have set both setVisibleXRangeMaximum and setVisibleXRangeMinimum to larger values, expecting more X-axis labels to show up.
I've ensured that the chart is large enough to accommodate the labels.
However, despite setting the visible range, only 6 labels are being displayed on the X-axis. Here’s the relevant part of the code:
fun setLineChart(
chart: LineChart,
values: java.util.ArrayList,
type: Int
) {
val yVals = java.util.ArrayList()
val yValsWithoutGaps = java.util.ArrayList()
if (values.size > 0) {
for (i in values.indices) {
//if(values.get(i).getyValue()>0)
if (values[i].yAxisVal1.toFloat() > 0F) {
yVals.add(Entry(i.toFloat(), values[i].yAxisVal1.toFloat()))
yValsWithoutGaps.add(Entry(i.toFloat(), values[i].yAxisVal1.toFloat()))
} else {
yVals.add(Entry(i.toFloat(), 0f))
}
}
}
val set1 = LineDataSet(yValsWithoutGaps, "")
chart.description.isEnabled = false
chart.setPinchZoom(false)
chart.isDoubleTapToZoomEnabled = false
chart.setDrawGridBackground(false)
chart.legend.isEnabled = false
set1.lineWidth = 3f
set1.circleRadius = 5f
set1.label = "Jun"
set1.mode = LineDataSet.Mode.CUBIC_BEZIER
set1.circleHoleRadius = 0f
set1.color = Color.parseColor("#E6A3FD")
set1.setCircleColor(Color.parseColor("#1A2857"))
set1.setDrawCircleHole(false)
set1.highLightColor = Color.parseColor("#E6A3FD")
set1.setDrawValues(false)
set1.setDrawHighlightIndicators(false)
val set2 = LineDataSet(yVals, "")
chart.description.isEnabled = false
chart.setPinchZoom(false)
chart.isDoubleTapToZoomEnabled = false
chart.setDrawGridBackground(false)
chart.legend.isEnabled = false
set2.lineWidth = 3f
set2.circleRadius = 0f
// set1.label = "Jun"
set2.mode = LineDataSet.Mode.CUBIC_BEZIER
set2.circleHoleRadius = 0f
set2.color = Color.parseColor("#00FFFFFF")
set2.setCircleColor(Color.parseColor("#00FFFFFF"))
set2.highLightColor = Color.parseColor("#00FFFFFF")
set2.setDrawValues(false)
set2.setDrawCircles(false)
set2.setDrawHighlightIndicators(false)
val lineData = LineData(set2, set1)
chart.data = lineData
chart.invalidate()
(lineData.getDataSetByIndex(0) as LineDataSet).circleHoleColor = Color.parseColor("#1A2857")
chart.description.isEnabled = false
chart.setDrawGridBackground(false)
chart.setClipValuesToContent(false)
chart.isHighlightPerTapEnabled = true
chart.setDrawMarkers(true)
val mv = XYMarkerView(context, DateAxisValueFormatter(values, type = type))
mv.chartView = chart // For bounds control
chart.marker = mv //
chart.xAxis.granularity = 1f
chart.xAxis.isGranularityEnabled = true
chart.xAxis.labelRotationAngle = 0f
chart.xAxis.axisMinimum = 0f
chart.xAxis.axisMaximum = values.size.toFloat()
chart.xAxis.setDrawGridLines(false)
chart.xAxis.setDrawAxisLine(true)
chart.xAxis.valueFormatter = DateAxisValueFormatter(values, type = type)
chart.xAxis.isEnabled = true
chart.xAxis.textSize = 12f
chart.xAxis.spaceMin = 1f
chart.xAxis.spaceMax = 1f
chart.xAxis.textColor = Color.parseColor("#484848")
chart.xAxis.position = XAxis.XAxisPosition.BOTTOM
chart.setXAxisRenderer(
CustomXAxisRenderer(
chart.viewPortHandler,
chart.xAxis,
chart.getTransformer(YAxis.AxisDependency.LEFT)
)
)
setYAxisLableStyle(chart.axisLeft, chart.axisRight)
chart.isDoubleTapToZoomEnabled = false
chart.minOffset = 0f
chart.setExtraOffsets(0f, 10f, 20f, 30f)
chart.contentRect[0f, 0f, 0f] = chart.height.toFloat()
chart.setTouchEnabled(true)
chart.isDragEnabled = true
chart.setScaleEnabled(false)
chart.isClickable = true
if (values.size > 6) {
chart.setVisibleXRangeMaximum(7f)
chart.setVisibleXRangeMinimum(7f)
} else {
chart.setVisibleXRangeMaximum(values.size.toFloat())
chart.setVisibleXRangeMinimum(values.size.toFloat())
}
if (type != 2) {
if (values.size > 7) {
chart.moveViewToX((values.size - 7).toFloat());
} else {
chart.moveViewToX(0f);
}
} else {
chart.moveViewToX(0f);
}
chart.invalidate()
}
fun setYAxisLableStyle(leftYAxis: YAxis, rightYAxis: YAxis) {
// Log.e("Max",maxValue.toString())
leftYAxis.axisMinimum = 0f
// leftYAxis.axisMaximum=maxValue
// leftYAxis.setLabelCount(5)
leftYAxis.removeAllLimitLines()
//leftYAxis.setDrawLabels(true)
//leftYAxis.setDrawAxisLine(true)
leftYAxis.textSize = 12f
// // leftYAxis.granularity=2f
//leftYAxis.granularity = maxOf(maxValue / 4, 1f)
leftYAxis.setDrawGridLines(false)
leftYAxis.setDrawZeroLine(false)
//leftYAxis.zeroLineWidth=3f
rightYAxis.isEnabled = false
}
class DateAxisValueFormatter(private val values: ArrayList, val type: Int) : ValueFormatter() {
var outputFormatType = "dd\nMMM"
var inputFormatType = "yyyy-MM-dd"
override fun getFormattedValue(value: Float): String {
return try {
if (type == 1) {
inputFormatType = Constants.DATE_TIME_FORMAT
outputFormatType = "hh:mma";
}
if (type == 2) {
outputFormatType = "EEE";
}
val inputFormat = SimpleDateFormat(inputFormatType, Locale.getDefault())
val outputFormat = SimpleDateFormat(outputFormatType, Locale.getDefault())
val index = value.toInt()
if (index in values.indices) {
val dateString = values[index].xAxisVal // Assuming GraphData has xAxixVal as a date string
val date = inputFormat.parse(dateString)
outputFormat.format(date) // Format date to "06 Nov"
} else {
value.toString() // Fallback to the raw value if out of bounds
}
} catch (e: Exception) {
e.printStackTrace()
value.toString() // Fallback in case of parsing error
}
}
override fun getAxisLabel(value: Float, axis: AxisBase?): String {
return try {
if (type == 1) {
inputFormatType = Constants.DATE_TIME_FORMAT
outputFormatType = "hh:mm\na";
}
if (type == 2) {
outputFormatType = "EEE\n ";
}
val inputFormat = SimpleDateFormat(inputFormatType, Locale.getDefault())
val outputFormat = SimpleDateFormat(outputFormatType, Locale.getDefault())
val index = value.toInt()
if (index in values.indices) {
val dateString = values[index].xAxisVal // Assuming GraphData has xAxixVal as a date string
val date = inputFormat.parse(dateString)
outputFormat.format(date) // Format date to "06 Nov"
} else {
"" // Fallback to the raw value if out of bounds
}
} catch (e: Exception) {
e.printStackTrace()
value.toString() // Fallback in case of parsing error
}
}
}
@SuppressLint("ViewConstructor")
class XYMarkerView(context: Context?, private val xAxisValueFormatter: IAxisValueFormatter) :
MarkerView(context, R.layout.custom_marker_view) {
private val tvContent: TextView = findViewById(R.id.marker_text)
private val rvRoot: RelativeLayout = findViewById(R.id.rlMarkerRoot)
private val format: DecimalFormat = DecimalFormat("###.0")
// runs every time the MarkerView is redrawn, can be used to update the
// content (user-interface)
override fun refreshContent(e: Entry, highlight: Highlight) {
tvContent.text = java.lang.String.format(
format.format(e.y.toInt())
)
tvContent.text = abs(e.y).toInt().toString()
if (abs(e.y).toInt() > 0) {
rvRoot.visibility = VISIBLE
} else {
rvRoot.visibility = GONE
}
super.refreshContent(e, highlight)
}
override fun getOffset(): MPPointF {
return MPPointF(-(width / 2).toFloat(), -height.toFloat())
}
}
class CustomXAxisRenderer(
viewPortHandler: ViewPortHandler?,
xAxis: XAxis?,
trans: Transformer?
) : XAxisRenderer(viewPortHandler, xAxis, trans) {
override fun drawLabel(
c: Canvas,
formattedLabel: String,
x: Float,
y: Float,
anchor: MPPointF,
angleDegrees: Float
) {
// Split the formatted label into multiple lines
val lines = formattedLabel.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
// Get the height of each line
val lineHeight = mAxisLabelPaint.textSize
// Calculate the vertical position for each line
val totalHeight = (lineHeight * lines.size) // Total height of the text
val startY = y - totalHeight / 2 + 35 // Center vertically
// Draw each line with adjusted vertical position
for (i in lines.indices) {
// Calculate the vertical position for each line
val lineY = startY + i * lineHeight
Utils.drawXAxisValue(
c,
lines[i], // The text for the current line
x, // X position is the same for all lines (centered)
lineY, // Adjusted vertical position
mAxisLabelPaint,
anchor,
angleDegrees
)
}
}
}
What I expected:
I want the chart to show more than 6 X-axis labels. Specifically, I want it to show 7 labels depending on the visible range.
What happens:
The chart only shows 6 X-axis labels, regardless of the values set in setVisibleXRangeMaximum() and setVisibleXRangeMinimum().
Additional information:
The dataset contains more than 6 data points.
I am using RecyclerView to display multiple charts, but this issue occurs even with a single chart.
I have tried adjusting the chart's size, but it doesn’t resolve the issue.
What I have tried:
Adjusting the visible range using setVisibleXRangeMaximum() and setVisibleXRangeMinimum().
Setting the X-axis label count using setLabelCount().
Calling chart.invalidate() to force a redraw after data changes.
Question:
Why does the chart display only 6 X-axis labels, even though I have set the visible range to be larger?
Is there something I'm missing when configuring the X-axis with setVisibleXRangeMaximum() and setVisibleXRangeMinimum()?
Any help or guidance on how to resolve this issue would be greatly appreciated. Thanks in advance!