Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MPAndroidChart define exact/fixed interval between values on x-axis (time)

I'm using in the app MPAndroidChart library and I have line graph like this now:

enter image description here

On X axis I have seconds and I want to have the same interval between values on X axis. Now I have 19:03 and 19:20 but I want 19:05, 19:10, 19:15 (so have 300 seconds interval)...

How can I do it?

Now I'm using this functionality:

 lineChart.setScaleMinima(115f, 1f);

but it's not soo good. Also I want it change from 5 minutes interval to 1 hour or 1 day.

Is this possible?

like image 450
Pepa Zapletal Avatar asked Jun 05 '18 18:06

Pepa Zapletal


1 Answers

tl;dr Set the X axis min and max values to multiples of the interval you want (e.g. multiples of 5), and set the axis granularity to an appropriate multiple of that same interval (e.g. 5).

Full Example Here's an example test program showing how to set the axis bounds and granularity to force the markers to be at some multiple of your choosing. The granularity option sets the minimum resolution for the axis, and setting the xMin and xMax to a multiple of that means your axis spacing will be a multiple of your choosing. Note that if, for example, you select a 5 minute interval you may get axis ticks at 10 minute spacing (or 15 or 20) to keep an appropriate number of axis lines.

EDIT: OP asked about a real time graph, so I updated the example to plot the sin wave in real time.

package com.project.testchart;

import android.graphics.Color;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private final Handler handler = new Handler();
    private ArrayList<Entry> data = new ArrayList<>();

    @Override
    protected void onPause() {
        super.onPause();
        handler.removeCallbacksAndMessages(null);
    }

    @Override
    protected void onResume() {
        super.onResume();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                addPointToChart();
                drawChart();
                handler.postDelayed(this, 250);
            }
        }, 250);
    }

    private void addPointToChart() {

        while( data.size() > 100 ) {
            data.remove(0);
        }

        lastX += 1f;
        float y = (float)Math.sin(lastX/5f);
        data.add(new Entry(lastX,y));
    }

    private void drawChart() {

        float textSize = 20f;

        LineDataSet line = new LineDataSet(data, "Sin");
        line.setLineWidth(5);
        line.setColor(Color.BLACK);
        line.setDrawValues(false);
        line.setDrawCircles(false);
        line.setHighLightColor(Color.TRANSPARENT);

        LineData lines = new LineData();
        lines.addDataSet(line);

        LineChart chart = findViewById(R.id.test_chart);
        chart.setData(lines);

        Description desc = new Description();
        desc.setText("");
        chart.setDescription(desc);
        chart.setDrawBorders(true);

        YAxis yAxisR = chart.getAxisRight();
        yAxisR.setDrawGridLines(false);
        yAxisR.setEnabled(false);

        YAxis yAxisL = chart.getAxisLeft();
        yAxisL.setDrawGridLines(true);
        yAxisL.setDrawTopYLabelEntry(true);
        yAxisL.setTextSize(textSize);

        XAxis xAxis = chart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setTextSize(textSize);

        float xMin = (float)Math.floor((line.getXMin()-xInterval)/xInterval)*xInterval;
        float xMax = (float)Math.ceil((line.getXMax()+xInterval)/xInterval)*xInterval;
        float xSpan = xMax - xMin;
        float xi = xSpan / 6; // approximately 6 labels
        float xGran = Math.max(xInterval,(float)Math.round(xi/xInterval)*xInterval);

        xAxis.setGranularity(xGran);
        xAxis.setAxisMinimum(xMin);
        xAxis.setAxisMaximum(xMax);

        Legend l = chart.getLegend();
        l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        l.setDrawInside(false);
        l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
        l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
        l.setTextSize(textSize);

        chart.setExtraBottomOffset(10f);
        chart.setExtraRightOffset(20f);

        chart.invalidate();
    }

    private float xInterval = 5f;
    private float lastX = 0f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        float xStart = 3f;
        float xEnd = 7f;
        for(int i = 0; i < 4; ++i) {
            float x = xStart + (i/3f)*(xEnd-xStart);
            float y = (float)Math.sin(x/5f);
            data.add(new Entry(x,y));
        }
        lastX = xEnd;

        drawChart();
    }
}

And the XML file

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.github.mikephil.charting.charts.LineChart
        android:id="@+id/test_chart"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_margin="32dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</android.support.constraint.ConstraintLayout>

Some screenshots for different data ranges

Example screenshots

like image 193
Tyler V Avatar answered Oct 25 '22 09:10

Tyler V