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

Posted

技术标签:

【中文标题】mpandroidchart - 如何避免 Y 轴中的重复值?【英文标题】:mpandroidchart - How can I avoid the repeated values in Y-Axis? 【发布时间】:2015-12-10 17:44:20 【问题描述】:

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

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

    限制缩放在 YAxis 中有重复值之前,因此停止图表上的无限放大 获取 YAxis 值并删除重复值。

【问题讨论】:

设置 x 和 y 最大值的限制 我认为在ios中是在最后一个版本中解决的,chart.getViewPortHandler().setMaximumScaleX(4f); chart.getViewPortHandler().setMaximumScaleY(4f);但它仍然无法在 android 中运行 【参考方案1】:

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

对我来说,解决办法是

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

我还为标签计数添加了 +1

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

希望对你有帮助

【讨论】:

您可以使用Math.round,而不是Math.ceil。为什么?阅读我的answer here【参考方案2】:

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

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

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

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

另一个例子:

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

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

【讨论】:

【参考方案3】:

虽然这是一个较老的问题,但我想添加到它以供将来参考。该库的较新版本有一个鲜为人知的功能,可以解决重复的标签,称为粒度。这比旧的解决方案更易于使用(但公平地说,这在发布时不可用)。

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

setGranularity(float granularity): 设置放大时轴的最小间隔。轴不 允许低于该限制。这可以用来避免标签 放大时重复。 setGranularityEnabled(boolean enabled): 启用/禁用轴值间隔的粒度控制。如果 启用,轴间隔不允许低于某个 粒度。

因此,在您的情况下,您需要将粒度设置为 0.1f,因为您有一位小数点。下面的sn-p代码应该避免轴上的重复值:

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

【讨论】:

【参考方案4】:

tl;dr您可以通过更改onChartScale 中的标签计数来做到这一点。

首先,您需要设置监听器:

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

您尝试获取顶部/底部绘制的值并检查在屏幕上绘制的内容。应用一些基本的计算,就可以了。

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

@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

值格式化程序和其他一切保持不变。

还有一些丑陋的屏幕截图表明它有效:D

【讨论】:

我可以看到两次 15.8ºC。这在哪里解决了重复的值?你只是在轴上放了两个值 @rguerra 您不能在轴上设置 很多 时。所以你可以另外限制缩放级别,但我怀疑你可以使用 MPChart 做得比这更好;) 我不认为我需要使用另一个库 :) 因为,这已经在 iOS 版本中工作了。他们已经可以在重复值之前限制缩放,设置axisMax和axisMin值。但在 Android 中,我们缩放的区域一直向右移动 它是开源的。你可以改变它。你的意思是在 android chart.getViewPortHandler().setMaximumScaleY(4f) 不起作用? 可能设置PinchZoom(false)。【参考方案5】:

这样的代码:

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

或:

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

当你得到数据时:

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

我手头没有代码。

【讨论】:

这改变了我的视口,当我尝试放大时,将视口向右移动【参考方案6】:

我以前从未使用过 MPAndroidCharts,但只是在这里和那里进行了一些搜索,我得到了这个我认为很有用的方法。

public void setLabelCount(int count, boolean force) 

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

        mLabelCount = count;
        mForceLabels = force;
    

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

另外,还有一种方法-

public int getLabelCount() 
        return mLabelCount;
    

这将返回轴上的标签数量。希望这会有所帮助。

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

【讨论】:

以上是关于mpandroidchart - 如何避免 Y 轴中的重复值?的主要内容,如果未能解决你的问题,请参考以下文章

Android 图表框架MPAndroidChartr如何不绘制右边的Y轴

mpandroidchart Y轴怎么显示整数

MPAndroidChart 开发使用总结及采坑记录

MPAndroidChart 开发使用总结及采坑记录

MPAndroidChart 开发使用总结及采坑记录

MPAndroidChart如何让y轴以非零值开始?