MPAndroidChart icon indicating copy to clipboard operation
MPAndroidChart copied to clipboard

The chart gets cut off and the rest stays white when scrolling programmatically.

Open a7asoft opened this issue 1 year ago • 0 comments

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. example1 example2

a7asoft avatar Sep 09 '24 09:09 a7asoft