Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
更新MPAndroidChart中的XAxis值_Android_Indexoutofboundsexception_Mpandroidchart - Fatal编程技术网

更新MPAndroidChart中的XAxis值

更新MPAndroidChart中的XAxis值,android,indexoutofboundsexception,mpandroidchart,Android,Indexoutofboundsexception,Mpandroidchart,我正在开发一个预算应用程序,在本例中,我有一个统计类,其中使用MPAndroidChart收集和填充每组费用的值。其思想是,当我们在微调器中选择不同的月份时,图表中显示的值会相应地更新。当当前月份的费用类别数与所选新月份的类别数相同时,此功能正常工作。另一方面,如果当前月份的类别数与所选月份的类别数不同,我将获得ArrayIndexOutOfBoundsException 每次在微调器中选择不同的月份时,我已经在创建此类的新对象,因此我的问题是,如何更新MyXaxiValueFormatter中

我正在开发一个预算应用程序,在本例中,我有一个统计类,其中使用MPAndroidChart收集和填充每组费用的值。其思想是,当我们在微调器中选择不同的月份时,图表中显示的值会相应地更新。当当前月份的费用类别数与所选新月份的类别数相同时,此功能正常工作。另一方面,如果当前月份的类别数与所选月份的类别数不同,我将获得ArrayIndexOutOfBoundsException

每次在微调器中选择不同的月份时,我已经在创建此类的新对象,因此我的问题是,如何更新MyXaxiValueFormatter中的mValues数组以避免出现此异常

Statistics.java

package com.robin.xbudget;

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;

import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
import com.github.mikephil.charting.utils.ColorTemplate;

import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class Statistics extends Fragment {
    private final String TAG = this.getClass().getSimpleName();

    StatisticsListener callback;

    private TextView mNumberIncomes;
    private TextView mNumberExpenses;
    private TextView mNumberDaysPassed;
    private TextView mNumberDaysRemaining;
    private LocalDate mLocalDateFirst;
    private LocalDate mLocalDateLast;
    private Spinner monthSpinner;
    private BarChart mBarChart;
    private BarDataSet mBarDataSet;
    private BarData mData;
    ArrayList<BarEntry> barEntries;


    @RequiresApi(api = Build.VERSION_CODES.O)
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_statistics, container, false);

        mNumberIncomes = (TextView) view.findViewById(R.id.number_incomes);
        mNumberExpenses = (TextView) view.findViewById(R.id.number_expenses);
        mNumberDaysPassed = (TextView) view.findViewById(R.id.days_passed_number);
        mNumberDaysRemaining = (TextView) view.findViewById(R.id.days_remaining_number);
        mLocalDateFirst = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        mLocalDateLast = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());

        mNumberIncomes.setText(String.valueOf(callback.getTotalIncomes()));
        mNumberExpenses.setText(String.valueOf(callback.getTotalExpenses()));

        mNumberDaysPassed.setText(String.valueOf(Period.between(mLocalDateFirst, LocalDate.now()).getDays()));
        mNumberDaysRemaining.setText(String.valueOf(Period.between(LocalDate.now(), mLocalDateLast).getDays()));

        monthSpinner = (Spinner) view.findViewById(R.id.spinner_month_stats);
        monthSpinner.setAdapter(callback.getArrayAdapter());

        monthSpinner.setSelection(callback.getSpinnerPosition());

        monthSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                callback.setPeriodSelected((String) monthSpinner.getAdapter().getItem(position));

                dataFiller();
                mBarChart.invalidate();

                Log.d(TAG, "onItemSelected called");
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        mBarChart = (BarChart) view.findViewById(R.id.bar_chart);
        dataFiller();

        return view;
    }

    public void dataFiller(){

        mBarChart.setDrawBarShadow(false);
        mBarChart.setDrawValueAboveBar(true);
        mBarChart.setMaxVisibleValueCount(50);
        mBarChart.setPinchZoom(false);
        mBarChart.setDrawGridBackground(false);

        barEntries = new ArrayList<>();

        int x = 0;

            for (String s : callback.getExpensesDataGroup()) {
            float value = 0;
            for (Transaction t : callback.getExpensesDataChild().get(s)) {
                value += t.getQuantity();
            }
            barEntries.add(new BarEntry((float) ++x, value));
        }

        //This is the graphic
        mBarDataSet = new BarDataSet(barEntries, "Expenses");
        mBarDataSet.setColors(ColorTemplate.COLORFUL_COLORS);
        mBarDataSet.notifyDataSetChanged();
        mData = new BarData(mBarDataSet);
        mData.setBarWidth(0.9f);

        mBarChart.setData(mData);

        String[] expenses = new String[callback.getExpensesDataGroup().size() + 1];
        expenses[0] = "Dummy";
        for (int i = 1; i <= callback.getExpensesDataGroup().size(); i++) {
            expenses[i] = callback.getExpensesDataGroup().get(i - 1);
        }

        Log.d(TAG, "Prior to mValues before: " + expenses.length);

        mBarChart.notifyDataSetChanged();
        XAxis xAxis = mBarChart.getXAxis();
        xAxis.setValueFormatter(new myXAxisValueFormatter(expenses));
        xAxis.setPosition(XAxis.XAxisPosition.TOP);
        xAxis.setGranularity(1f);
        //xAxis.setCenterAxisLabels(true);
        //xAxis.setAxisMinimum(1);

    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try{
            callback = (StatisticsListener)context;
        }catch(ClassCastException cce){
            throw new ClassCastException("Class must implement StatisticListener");
        }
    }


    class myXAxisValueFormatter extends IndexAxisValueFormatter {

        private String[] mValues;
        public myXAxisValueFormatter(String[]values) {
            this.mValues = values;
        }

        @Override
        public String getFormattedValue(float value) {
            return mValues[(int)value];
        }
    }

    interface StatisticsListener{

        double getTotalIncomes();
        double getTotalExpenses();

        Map<String, List<Transaction>> getExpensesDataChild();
        List<String> getExpensesDataGroup();
        ArrayAdapter getArrayAdapter();

        void setPeriodSelected(String periodSelected);
        int getSpinnerPosition();
    }
}

您需要检查getFormattedValue中的值,因为它可以是<0或>=mValues.length

class myXAxisValueFormatter extends IndexAxisValueFormatter {

    private String[] mValues;
    public myXAxisValueFormatter(String[]values) {
        this.mValues = values;
    }

    @Override
    public String getFormattedValue(float value) {
        int intValue = (int)value;
        if (intValue < 0 || intValue >= mValues.length){
            return "";
        } else {
            return mValues[intValue];
        }
    }
}
类myXAxisValueFormatter扩展了IndexAxisValueFormatter{ 私有字符串[]mValues; 公共MyXaxiValueFormatter(字符串[]值){ this.mValues=值; } @凌驾 公共字符串getFormattedValue(浮点值){ int值=(int)值; if(intValue<0 | | intValue>=mValues.length){ 返回“”; }否则{ 返回mValues[intValue]; } } }
class myXAxisValueFormatter extends IndexAxisValueFormatter {

    private String[] mValues;
    public myXAxisValueFormatter(String[]values) {
        this.mValues = values;
    }

    @Override
    public String getFormattedValue(float value) {
        int intValue = (int)value;
        if (intValue < 0 || intValue >= mValues.length){
            return "";
        } else {
            return mValues[intValue];
        }
    }
}