MPAndroidChart определяет точный / фиксированный интервал между значениями по оси x (время)

Pepa Zapletal спросил: 12 мая 2018 в 04:52 в: android

Я использую в библиотеке приложения MPAndroidChart, и теперь у меня есть линейный граф:

На оси X у меня есть секунды, и я хочу иметь один и тот же интервал между значениями по оси X. Теперь у меня 19:03 и 19:20, но я хочу 19:05, 19:10, 19:15 (так что есть интервал в 300 секунд) ...

Как я могу это сделать?

Теперь я использую эту функциональность:

 lineChart.setScaleMinima(115f, 1f);

, но это не так хорошо. Также я хочу, чтобы он менялся от 5 минут до 1 часа или 1 дня.

Возможно ли это?

1 ответ

Tyler V ответил: 03 июня 2018 в 11:31

tl; dr Задайте минимальное и максимальное значения оси X, чтобы умножить на нужный интервал (например, кратные 5), и установите гранулярность оси на соответствующий кратный один и тот же интервал (например, 5).

Полный пример Вот пример тестовой программы, показывающей, как установить границы и гранулярность оси, чтобы заставить маркеры быть несколькими кратными по вашему выбору. Параметр детализации задает минимальное разрешение для оси и устанавливает xMin и xMax в несколько раз, что означает, что расстояние между вами будет кратно вашему выбору. Обратите внимание: если вы, например, выберете 5-минутный интервал, вы можете получить тики оси с интервалом в 10 минут (или 15 или 20), чтобы сохранить соответствующее количество осевых линий.

EDIT: OP спросил о График реального времени, поэтому я обновил этот пример, чтобы построить кривую sin в реальном времени.

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();
    }
}

И файл XML

<?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>

Некоторые скриншоты для разных диапазонов данных

Pepa Zapletal ответил: 03 июня 2018 в 10:09
Я тестировал с помощью setGranularity в своем приложении, но он не работает для меня. Я установил xInterval = 300 (5 минут в секундах) и xMin у меня -300; xMax = 2469600 (секунды в будущем), и я хочу 5-минутный интервал по оси X между этими точками. Если я использую ваш код, у меня есть полный график на экране сразу с неправильным интервалом. Посмотрите на этот снимок экрана: ibb.co/fptWc8 (обратите внимание, что я отключил масштабирование, я хочу только прокручивать влево / вправо на графике)
Tyler V ответил: 03 июня 2018 в 11:14
Поскольку у вас есть эти строки данных на вашем графике, вы хотите получить только xMin и xMax из своего набора данных (LineDataSet для белой строки), а не на LineData. Кроме того, ваши необработанные данные x за считанные минуты или некоторые меньшие инкременты данных?
Pepa Zapletal ответил: 03 июня 2018 в 02:00
Мои данные строки x находятся в секундах. Также обратите внимание, что интервал между значениями x не обязательно должен быть одним и тем же, а некоторые значения x могут отсутствовать. Пример значений х: 15, 30, 42, 60, 85..и интервал по оси х должен быть всегда 5 минут (или 10 минут ...)
Tyler V ответил: 03 июня 2018 в 11:25
Я обновил ответ, чтобы установить гранулярность динамически на основе диапазона видимых данных и приблизительного количества желаемых меток. Как я уже говорил, вам нужно получить xMin и xMax из LineDataSet для вашей белой строки и установить xInterval в секундах (например, 300 на 5-минутные интервалы). Если вы обнаружите, что ваши диапазоны таковы, что вы все еще получаете несколько ярлыков, вы можете попробовать изменить желаемое количество меток (здесь 6).
Pepa Zapletal ответил: 04 июня 2018 в 11:08
Это все еще не работает нормально для меня. Но setScaleMinima () выглядит лучше, но я не знаю, как вычислить правильный коэффициент scaleX. У вас есть какое-то представление об этом?