mpandroidchart - 如何避免Y轴中的重复值?

时间:2022-09-26 19:13:26

I want to avoid the repeated values and the -0 values in Y-Axis, avoiding the image situation.

我想避免重复值和Y轴中的-0值,避免图像情况。

I have these ideas to solve this, but any solution:

我有这些想法来解决这个问题,但任何解决方案:

  1. Limit the zoom before having repeated values in YAxis, therefore stop the infinite zoom-in on the chart
  2. 在YAxis中重复值之前限制缩放,因此停止图表上的无限放大

  3. Get the YAxis values and remove the duplicate values.
  4. 获取YAxis值并删除重复值。

mpandroidchart  - 如何避免Y轴中的重复值?

6 个解决方案

#1


3  

tl;dr You can do this by changing the label count in onChartScale.

tl; dr您可以通过更改onChartScale中的标签计数来完成此操作。

First, you want your listener set up:

首先,您希望您的听众设置:

chart.setOnChartGestureListener(this); // set a listener ;)

You try to get the top/bottom drawn values and check what gets drawn on the screen. Apply some basic calculations, and you're set.

您尝试获取顶部/底部绘制的值并检查屏幕上绘制的内容。应用一些基本计算,然后进行设置。

The following code will draw 2 labels if the zoom level gets (too) high and up to 9 otherwise:

如果缩放级别(太高)高达9,则以下代码将绘制2个标签:

@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
    final YAxis yAxis = mChart.getAxisLeft();
    final Transformer transformer = mChart.getTransformer(YAxis.AxisDependency.LEFT);

    // ...minor dirty hack
    final PointD top = transformer.getValuesByTouchPoint(0, 0);
    final PointD bottom = transformer.getValuesByTouchPoint(0, mChart.getHeight());
    final int diff = (int)(top.y - bottom.y);

    // draw 2-9 axis labels
    final int count = Math.min(9, Math.max(diff, 2));

    Log.d("scale", String.format("scale %f: diff %d and count %d", scaleY, diff, count));

    // "force" the count, for there are drawing issues where none get drawn on high zoom levels (just try it out)
    yAxis.setLabelCount(count, true);
}

// todo implement other interface methods

The value formatter and everything else stays the same.

值formatter和其他所有内容保持不变。

And some ugly screenshot to show that it works :D

还有一些丑陋的截图显示它有效:D

mpandroidchart  - 如何避免Y轴中的重复值?

#2


2  

code like this:

像这样的代码:

    mchart.setAutoScaleMinMaxEnabled(false);
    mchart.getAxisLeft().setAxisMaxValue(10);
    mchart.getAxisLeft().setAxisMinValue(5);
    mchart.getAxisRight().setAxisMaxValue(10);
    mchart.getAxisRight().setAxisMinValue(5);

or:

boolean a = isReady;
 mchart.getAxisLeft().setFormater(new format(float b){ return "" ;})

When u get data :

当你获得数据时:

    mchart.setAutoScaleMinMaxEnabled(true);
    mchart.getAxisLeft().resetAxisMaxValue();
    mchart.getAxisLeft().resetAxisMinValue();
    mchart.getAxisRight().resetAxisMaxValue();
    mchart.getAxisRight().resetAxisMinValue(5);

I have no code by my hand.

我的手上没有代码。

#3


2  

Though this is an older question I'd like to add to it for future reference. Newer versions of the library have a little known feature that resolves the duplicated labels, called granularity. This is way simpler to use than the older solutions (though to be fair, this wasn't available at the time those were posted).

虽然这是一个较旧的问题,但我想添加它以供将来参考。较新版本的库具有一些鲜为人知的功能,可以解析重复的标签,称为粒度。这比使用旧解决方案更简单(尽管公平地说,这些在发布时尚未提供)。

You can always check the latest AxisBase Javadocs (3.0.0-beta1) for a more detailed explanation. Here are the relevant methods:

您可以随时查看最新的AxisBase Javadocs(3.0.0-beta1)以获得更详细的说明。以下是相关方法:

  • setGranularity(float granularity): Set a minimum interval for the axis when zooming in. The axis is not allowed to go below that limit. This can be used to avoid label duplicating when zooming in.
  • setGranularity(float granularity):设置放大时轴的最小间隔。不允许轴低于该限制。这可用于避免放大时标签重复。

  • setGranularityEnabled(boolean enabled): Enabled/disable granularity control on axis value intervals. If enabled, the axis interval is not allowed to go below a certain granularity.
  • setGranularityEnabled(boolean enabled):启用/禁用轴值间隔的粒度控制。如果启用,则不允许轴间隔低于某个粒度。

So in your case you'd need to set the granularity to 0.1f since you have one decimal point. The following snippet of code should avoid the repeated values on the axis:

因此,在您的情况下,您需要将粒度设置为0.1f,因为您有一个小数点。以下代码片段应避免轴上的重复值:

YAxis yAxis = mChart.getAxisLeft();
yAxis.setGranularityEnabled(true);
yAxis.setGranularity(0.1f);

#4


0  

I have never used MPAndroidCharts before, but just a little search here and there got me this method which I think would be useful.

我之前从未使用过MPAndroidCharts,但只是在这里进行了一点搜索,我认为这种方法对我有用。

public void setLabelCount(int count, boolean force) {

        if (count > 25)
            count = 25;
        if (count < 2)
            count = 2;

        mLabelCount = count;
        mForceLabels = force;
    }

The description says that "exact specified count of labels will be drawn and evenly distributed alongside the axis". If you can make it work in your favor, you might be able to limit the zoom.

描述说“将绘制精确指定的标签数量并沿轴线均匀分布”。如果你能使它对你有利,你可以限制缩放。

Also, there is another method-

此外,还有另一种方法 -

public int getLabelCount() {
        return mLabelCount;
    }

This returns the number of labels on the axis. Hope this helps.

这将返回轴上的标签数。希望这可以帮助。

https://github.com/PhilJay/MPAndroidChart/blob/5a15715b25991e3d61d27d552f9eba45975d65e7/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java

#5


0  

You can set granularity to your required value to prevent the repetition when zoomed.

您可以将粒度设置为所需的值,以防止在缩放时重复。

mBarChart.getAxisLeft().setGranularity(1f);  // y-axis scale will be 0,1,2,3,4....
mBarChart.getAxisLeft().setGranularityEnabled(true);

If you want to set granularity dynamically, then implement IAxisValueFormatter and compare the return value to get the difference and set Granularity to that difference.

如果要动态设置粒度,则实现IAxisValueFormatter并比较返回值以获取差异并将粒度设置为该差异。

    private float yAxisScaleDifference = -1;
    private boolean granularitySet = false;
    //say the values returned by IAxisFormatter is in hundreds: 100, 200, 300...
    mBarChart.getAxisLeft.setValueFormatter(new IAxisValueFormatter() {
    @Override
    public String getFormattedValue(float v, AxisBase axisBase) {
        if(!granularitySet) {

            if(yAxisScaleDifference == -1) {
                yAxisScaleDifference = v;  //10
            }
            else {
                float diff = v - yAxisScaleDifference;  //200 - 100 = 100
                if(diff >= 1000) {
                    yAxisLeft.setGranularity(1000f);  
                }
                else if(diff >= 100) {
                    yAxisLeft.setGranularity(100f);  //set to 100
                }
                else if(diff >= 1f) {
                    yAxisLeft.setGranularity(1f);
                }
                granularitySet =true;
            }
        }
        return val;
    }
});

Another Example:

say Y-Axis returns [1200,3400,8000,9000....]
  first time: 1200
  second time: 3400 - 1200 = 2200
  granularity set to 1000

If the difference is not uniform you have to use array to store the differences and take the average to get the right granularity.

如果差异不均匀,则必须使用数组来存储差异,并使用平均值来获得正确的粒度。

#6


0  

If you are using IAxisValueFormatter the problem might be in the conversion of float to Int when trying to access the values array.

如果您正在使用IAxisValueFormatter,则在尝试访问values数组时,问题可能在于将float转换为Int。

For me the solution was to

对我来说,解决方案是

IAxisValueFormatter numAppointmentsXAxisFormatter = new IAxisValueFormatter() {
    @Override
    public String getFormattedValue(float value, AxisBase axis) {

        int index = (int)Math.ceil(value);
        if(index < 0){
            index = 0;
        }else if(index >= numAppointmentsLabels.size()){
            index = numAppointmentsLabels.size()-1;
        }

        return numAppointmentsLabels.get(index);
    }
};

I also added +1 to the label count

我还在标签数上添加了+1

chart.getXAxis().setLabelCount(numValue+1, true);

Hope it helps

希望能帮助到你

#1


3  

tl;dr You can do this by changing the label count in onChartScale.

tl; dr您可以通过更改onChartScale中的标签计数来完成此操作。

First, you want your listener set up:

首先,您希望您的听众设置:

chart.setOnChartGestureListener(this); // set a listener ;)

You try to get the top/bottom drawn values and check what gets drawn on the screen. Apply some basic calculations, and you're set.

您尝试获取顶部/底部绘制的值并检查屏幕上绘制的内容。应用一些基本计算,然后进行设置。

The following code will draw 2 labels if the zoom level gets (too) high and up to 9 otherwise:

如果缩放级别(太高)高达9,则以下代码将绘制2个标签:

@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
    final YAxis yAxis = mChart.getAxisLeft();
    final Transformer transformer = mChart.getTransformer(YAxis.AxisDependency.LEFT);

    // ...minor dirty hack
    final PointD top = transformer.getValuesByTouchPoint(0, 0);
    final PointD bottom = transformer.getValuesByTouchPoint(0, mChart.getHeight());
    final int diff = (int)(top.y - bottom.y);

    // draw 2-9 axis labels
    final int count = Math.min(9, Math.max(diff, 2));

    Log.d("scale", String.format("scale %f: diff %d and count %d", scaleY, diff, count));

    // "force" the count, for there are drawing issues where none get drawn on high zoom levels (just try it out)
    yAxis.setLabelCount(count, true);
}

// todo implement other interface methods

The value formatter and everything else stays the same.

值formatter和其他所有内容保持不变。

And some ugly screenshot to show that it works :D

还有一些丑陋的截图显示它有效:D

mpandroidchart  - 如何避免Y轴中的重复值?

#2


2  

code like this:

像这样的代码:

    mchart.setAutoScaleMinMaxEnabled(false);
    mchart.getAxisLeft().setAxisMaxValue(10);
    mchart.getAxisLeft().setAxisMinValue(5);
    mchart.getAxisRight().setAxisMaxValue(10);
    mchart.getAxisRight().setAxisMinValue(5);

or:

boolean a = isReady;
 mchart.getAxisLeft().setFormater(new format(float b){ return "" ;})

When u get data :

当你获得数据时:

    mchart.setAutoScaleMinMaxEnabled(true);
    mchart.getAxisLeft().resetAxisMaxValue();
    mchart.getAxisLeft().resetAxisMinValue();
    mchart.getAxisRight().resetAxisMaxValue();
    mchart.getAxisRight().resetAxisMinValue(5);

I have no code by my hand.

我的手上没有代码。

#3


2  

Though this is an older question I'd like to add to it for future reference. Newer versions of the library have a little known feature that resolves the duplicated labels, called granularity. This is way simpler to use than the older solutions (though to be fair, this wasn't available at the time those were posted).

虽然这是一个较旧的问题,但我想添加它以供将来参考。较新版本的库具有一些鲜为人知的功能,可以解析重复的标签,称为粒度。这比使用旧解决方案更简单(尽管公平地说,这些在发布时尚未提供)。

You can always check the latest AxisBase Javadocs (3.0.0-beta1) for a more detailed explanation. Here are the relevant methods:

您可以随时查看最新的AxisBase Javadocs(3.0.0-beta1)以获得更详细的说明。以下是相关方法:

  • setGranularity(float granularity): Set a minimum interval for the axis when zooming in. The axis is not allowed to go below that limit. This can be used to avoid label duplicating when zooming in.
  • setGranularity(float granularity):设置放大时轴的最小间隔。不允许轴低于该限制。这可用于避免放大时标签重复。

  • setGranularityEnabled(boolean enabled): Enabled/disable granularity control on axis value intervals. If enabled, the axis interval is not allowed to go below a certain granularity.
  • setGranularityEnabled(boolean enabled):启用/禁用轴值间隔的粒度控制。如果启用,则不允许轴间隔低于某个粒度。

So in your case you'd need to set the granularity to 0.1f since you have one decimal point. The following snippet of code should avoid the repeated values on the axis:

因此,在您的情况下,您需要将粒度设置为0.1f,因为您有一个小数点。以下代码片段应避免轴上的重复值:

YAxis yAxis = mChart.getAxisLeft();
yAxis.setGranularityEnabled(true);
yAxis.setGranularity(0.1f);

#4


0  

I have never used MPAndroidCharts before, but just a little search here and there got me this method which I think would be useful.

我之前从未使用过MPAndroidCharts,但只是在这里进行了一点搜索,我认为这种方法对我有用。

public void setLabelCount(int count, boolean force) {

        if (count > 25)
            count = 25;
        if (count < 2)
            count = 2;

        mLabelCount = count;
        mForceLabels = force;
    }

The description says that "exact specified count of labels will be drawn and evenly distributed alongside the axis". If you can make it work in your favor, you might be able to limit the zoom.

描述说“将绘制精确指定的标签数量并沿轴线均匀分布”。如果你能使它对你有利,你可以限制缩放。

Also, there is another method-

此外,还有另一种方法 -

public int getLabelCount() {
        return mLabelCount;
    }

This returns the number of labels on the axis. Hope this helps.

这将返回轴上的标签数。希望这可以帮助。

https://github.com/PhilJay/MPAndroidChart/blob/5a15715b25991e3d61d27d552f9eba45975d65e7/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java

#5


0  

You can set granularity to your required value to prevent the repetition when zoomed.

您可以将粒度设置为所需的值,以防止在缩放时重复。

mBarChart.getAxisLeft().setGranularity(1f);  // y-axis scale will be 0,1,2,3,4....
mBarChart.getAxisLeft().setGranularityEnabled(true);

If you want to set granularity dynamically, then implement IAxisValueFormatter and compare the return value to get the difference and set Granularity to that difference.

如果要动态设置粒度,则实现IAxisValueFormatter并比较返回值以获取差异并将粒度设置为该差异。

    private float yAxisScaleDifference = -1;
    private boolean granularitySet = false;
    //say the values returned by IAxisFormatter is in hundreds: 100, 200, 300...
    mBarChart.getAxisLeft.setValueFormatter(new IAxisValueFormatter() {
    @Override
    public String getFormattedValue(float v, AxisBase axisBase) {
        if(!granularitySet) {

            if(yAxisScaleDifference == -1) {
                yAxisScaleDifference = v;  //10
            }
            else {
                float diff = v - yAxisScaleDifference;  //200 - 100 = 100
                if(diff >= 1000) {
                    yAxisLeft.setGranularity(1000f);  
                }
                else if(diff >= 100) {
                    yAxisLeft.setGranularity(100f);  //set to 100
                }
                else if(diff >= 1f) {
                    yAxisLeft.setGranularity(1f);
                }
                granularitySet =true;
            }
        }
        return val;
    }
});

Another Example:

say Y-Axis returns [1200,3400,8000,9000....]
  first time: 1200
  second time: 3400 - 1200 = 2200
  granularity set to 1000

If the difference is not uniform you have to use array to store the differences and take the average to get the right granularity.

如果差异不均匀,则必须使用数组来存储差异,并使用平均值来获得正确的粒度。

#6


0  

If you are using IAxisValueFormatter the problem might be in the conversion of float to Int when trying to access the values array.

如果您正在使用IAxisValueFormatter,则在尝试访问values数组时,问题可能在于将float转换为Int。

For me the solution was to

对我来说,解决方案是

IAxisValueFormatter numAppointmentsXAxisFormatter = new IAxisValueFormatter() {
    @Override
    public String getFormattedValue(float value, AxisBase axis) {

        int index = (int)Math.ceil(value);
        if(index < 0){
            index = 0;
        }else if(index >= numAppointmentsLabels.size()){
            index = numAppointmentsLabels.size()-1;
        }

        return numAppointmentsLabels.get(index);
    }
};

I also added +1 to the label count

我还在标签数上添加了+1

chart.getXAxis().setLabelCount(numValue+1, true);

Hope it helps

希望能帮助到你