Getting duplicate values at xAxis MPChart

2019-02-26 20:06发布

问题:

Right Now I am facing this issue. I am getting repeated values in xAxis the first one and the last one.And graph values are not according to the values at respective x-axis values. and the second issue is if I want to display the values not in float but in int Rounded and change the their color to white.

ArrayList<String> xlabels = new ArrayList<String>();
        xlabels.add("Jan");
        xlabels.add("Feb");
        xlabels.add("Mar");
        xlabels.add("Apr");
        xlabels.add("May");
        xlabels.add("Jun");

        ArrayList<String> values = new ArrayList<String>();
        values.add("1");
        values.add("20");
        values.add("10");
        values.add("80");
        values.add("90");
        values.add("24");

        showLineChart(clickChart,xlabels,values,mColors[3]);

showLineChart Method:

private void showLineChart(LineChart chart,final List<String> xLabels, List<String> values,int color){
        List<Entry> entries = new ArrayList<Entry>();
        for(int i=0;i<values.size();i++){
            entries.add(new Entry(i, Integer.parseInt(values.get(i))));
        }



        LineDataSet dataSet = new LineDataSet(entries, "Numbers");
        dataSet.setLineWidth(1.75f);
        dataSet.setCircleRadius(5f);
        dataSet.setCircleHoleRadius(2.5f);
        dataSet.setColor(Color.WHITE);
        dataSet.setCircleColor(Color.WHITE);
        dataSet.setHighLightColor(Color.WHITE);
        dataSet.setDrawValues(true);


        LineData data = new LineData(dataSet);
        ((LineDataSet) data.getDataSetByIndex(0)).setCircleColorHole(color);

        chart.getDescription().setEnabled(false);

        chart.setDrawGridBackground(false);

        chart.setTouchEnabled(true);

        chart.setBorderColor(Color.WHITE);

        chart.setDragEnabled(true);
        chart.setScaleEnabled(true);


        chart.setPinchZoom(false);

        chart.setBackgroundColor(color);

        YAxis yAxisLeft = chart.getAxisLeft();
        yAxisLeft.setTextColor(Color.WHITE);
        yAxisLeft.setAxisLineColor(Color.WHITE);


        YAxis yAxisRight = chart.getAxisRight();
        yAxisRight.setTextColor(Color.WHITE);
        yAxisRight.setAxisLineColor(Color.WHITE);

        XAxis xAxis = chart.getXAxis();
        xAxis.setTextColor(Color.WHITE);
        xAxis.setAxisLineColor(Color.WHITE);
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setAvoidFirstLastClipping(false);
        xAxis.isDrawLabelsEnabled();
        xAxis.setDrawGridLines(false);
        xAxis.setValueFormatter(new IAxisValueFormatter() {

            @Override
            public String getFormattedValue(float value, AxisBase axis) {

                return xLabels.get((int)value);
            }


        });
        chart.animateX(2500);
        chart.setData(data);
        chart.invalidate();
    }

回答1:

I was facing the same issue to resolve it add the following line:

xAxis.setGranularityEnabled(true);

Check the link for more details about Axis.



回答2:

Setting granularity alone did not solve my problem. Here's what I had to do:

XAxis xAxis = chart.getXAxis();
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setLabelCount(xLabels.size(),false); // yes, false. This is intentional
xAxis.setValueFormatter(new MyXAxisValueFormatter(xLabels));
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);

And, this is my simple implementation of the IAxisValueFormatter. You may change it as per your needs:

public class MyXAxisValueFormatter implements IAxisValueFormatter {
        private ArrayList<String> mValues;

        MyXAxisValueFormatter(ArrayList<String> values) {
            this.mValues = values;
        }

        @Override
        public String getFormattedValue(float value, AxisBase axis) {
            int index = Math.round(value);

            if(index >= mValues.size()){
                index = mValues.size()-1;
            }
            return mValues.get(index);
        }
    }

It's very important to know why every problem occurs and why the solution code solves the problem. So, here's the analysis part:

Why does this occur?

Even in cases where your data lies at whole number positions on the x-axis (0,1,2...), the actual label isn't necessarily placed at those specific positions. For example, the label for the data at 1.00f might be at 0.92f. (This is how the library handles it, not sure why). So, when you try to cast the float value to an int, you do not get the exact position. From the earlier example, the label at 0.92f when cast to an int would be a 0, not 1.

How does this code solve the problem?

If you understood the above section, then this must not be necessary. Anyways, here's the reasoning. From my test results, I noticed that the label position was at all times nearby the actual x. So, the Math.round() method was perfect to get the proper index out of the float value.

Additionally, I set the parameter forced as a false in the setLabelCount method because I wanted the labels to hide as the user zooms-in in the x-axis.