MPAndroidChart
MPAndroidChart copied to clipboard
The chart gets cut off and the rest stays white when scrolling programmatically.
I want to synchronize the scrolling of a RecyclerView with a LineChart, but I'm having issues. When the chart is scrolled to a part that is not initially visible, it simply shows as blank.
I'm using version 3.1.0.
RecyclerView scroll:
binding.rvDaysDetails.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
binding.chart1.scrollBy(scrollX - oldScrollX, scrollY - oldScrollY);
binding.chart1.notifyDataSetChanged();
binding.chart1.invalidate();
});
LineGraph scroll:
lineChart.setOnChartGestureListener(new OnChartGestureListener() {
@Override
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
@Override
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
@Override
public void onChartLongPressed(MotionEvent me) {}
@Override
public void onChartDoubleTapped(MotionEvent me) {}
@Override
public void onChartSingleTapped(MotionEvent me) {}
@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {}
@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {}
@Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {
binding.rvDaysDetails.scrollBy((int) -dX, (int) -dY);
lineChart.notifyDataSetChanged();
lineChart.invalidate();
}
});
The scrolling works fine, the only issue is that the chart gets cut off.
This is my whole graph code:
public void setLineChartData(LineChart lineChart) {
float density = getDensity();
lineValues = generateData();
LineDataSet lineDataSet = new LineDataSet(lineValues, "");
lineDataSet.setColor(getResources().getColor(R.color.grey_line));
lineDataSet.setDrawCircles(true);
lineDataSet.setCircleColor(Color.BLACK);
lineDataSet.setCircleRadius(3f);
lineDataSet.setCircleHoleRadius(3f);
lineDataSet.setDrawFilled(false);
lineDataSet.setDrawValues(false);
lineDataSet.setMode(LineDataSet.Mode.LINEAR);
LineData data = new LineData(lineDataSet);
lineChart.setData(data);
lineChart.getDescription().setEnabled(false);
lineChart.getLegend().setEnabled(false);
XAxis xAxisTop = lineChart.getXAxis();
xAxisTop.setPosition(XAxis.XAxisPosition.TOP);
xAxisTop.setDrawLabels(true);
xAxisTop.setDrawGridLines(false);
xAxisTop.setDrawAxisLine(false);
xAxisTop.setGranularity(10f);
xAxisTop.setSpaceMin(5f);
xAxisTop.setSpaceMax(5f);
xAxisTop.setTextSize(10f);
xAxisTop.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
int index = (int) (value / 10);
if (index >= 0 && index < lineValues.size()) {
return String.format(Locale.getDefault(), "%.1f°C", lineValues.get(index).getY());
}
return "";
}
});
lineChart.setExtraLeftOffset(0f);
lineChart.setExtraRightOffset(0f);
lineChart.setExtraTopOffset(15f);
lineChart.setExtraBottomOffset(0f);
YAxis yAxisLeft = lineChart.getAxisLeft();
yAxisLeft.setDrawLabels(false);
yAxisLeft.setDrawGridLines(false);
yAxisLeft.setDrawAxisLine(false);
yAxisLeft.setDrawLimitLinesBehindData(true);
yAxisLeft.setEnabled(true);
float minY = yAxisLeft.getAxisMinimum();
float maxY = yAxisLeft.getAxisMaximum();
float interval = (maxY - minY) / 12;
for (int i = 0; i <= 12; i++) {
LimitLine limitLine = new LimitLine(minY + i * interval, "");
if (i == 6) {
limitLine.setLineColor(ContextCompat.getColor(requireContext(), R.color.day_blue));
limitLine.setLineWidth(1f);
} else {
limitLine.setLineColor(ContextCompat.getColor(requireContext(), R.color.grey_details));
limitLine.setLineWidth(0.5f);
}
yAxisLeft.addLimitLine(limitLine);
}
YAxis yAxisRight = lineChart.getAxisRight();
yAxisRight.setEnabled(false);
lineChart.setDrawBorders(false);
lineChart.setBackgroundColor(getResources().getColor(R.color.white));
lineChart.setScaleEnabled(false);
lineChart.setDragEnabled(true);
float referenceDensity = 2.0f;
float referenceVisibleXRange = 46.7f;
float slope = 16.08f;
float adjustedVisibleXRange = referenceVisibleXRange + (slope * (density - referenceDensity));
lineChart.setVisibleXRangeMaximum(adjustedVisibleXRange);
lineChart.setVisibleXRangeMinimum(adjustedVisibleXRange);
lineChart.setViewPortOffsets(0f, 40f, 0f, 0f);
lineChart.animateXY(250, 250, Easing.EaseInCubic);
lineChart.moveViewToX(-5f);
lineChart.setOnChartGestureListener(new OnChartGestureListener() {
@Override
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
scrollingChart = true;
}
@Override
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
scrollingChart = false;
}
@Override
public void onChartLongPressed(MotionEvent me) {
}
@Override
public void onChartDoubleTapped(MotionEvent me) {
}
@Override
public void onChartSingleTapped(MotionEvent me) {
}
@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
}
@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
}
@Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {
binding.rvDaysDetails.scrollBy((int) -dX, (int) -dY);
lineChart.notifyDataSetChanged();
lineChart.invalidate();
}
});
}
Example1 -> Before scroll.
Example2 -> After scroll.