【问题标题】:MPAndroidChart: Justifiy grid and labels to midnight (00:00) on date formattingMPAndroidChart:在日期格式上将网格和标签对齐到午夜(00:00)
【发布时间】:2021-04-30 18:01:49
【问题描述】:

问题:

MPAndroidChart 可以很好地计算十进制值的网格和标签位置,但对于日期/时间轴则不然。

我想将标签位置精确到午夜,例如。 x 轴范围为 4 天:

[26.1-00h, 27.1-00h, 28.1-00h,29.1-00h, 30.1-00h]

或者如果范围是例如。仅 2 天:

[26.1-00h, 26.1-12h, 27.1-00h, 27.1-12h,28.1-00h]

等等

我尝试了什么:

  1. 正在调整MPAndroidChart x-axis date/time label formatting 的解决方案,但它不适用于 MPAndroidChart 的最新版本 3.1.0。

  2. 使用 setAxisMinimum() 和 setAxisMaximum() 将图表的最小值和最大值修正为午夜时间戳。

  3. 玩不同的值缩放。

  4. 使用 setGranularity() 将粒度设置为一整天,但随后数据点会从其原始位置快速移动到 ganularity 位置。

网格原点和间距的计算似乎在AxisRenderer类的computeAxisValues()中完成,但是这个类不能重载(?)

有没有办法在不改变库的情况下控制x轴标签的定位?

【问题讨论】:

    标签: android mpandroidchart linechart


    【解决方案1】:

    回答我自己的问题:

    1. 添加日期格式以及缩放常数:
        private static final long MS_PER_XSCALE = 1000 * 60; // scale to minute resolution
        private static final long XSCALE_ONE_DAY = 60 * 24; // one day
    
        private final SimpleDateFormat xAxisDataFormat_DD_MMM_H = new SimpleDateFormat("dd.MMM'_'H'h'", Locale.ENGLISH);
        private final SimpleDateFormat xAxisDataFormat_DD_MMM = new SimpleDateFormat("dd.MMM", Locale.ENGLISH);
        private static final long TIMEOFFSET = TimeZone.getDefault().getRawOffset();
    
    1. 在Activity的onCreate()中设置自定义的Date Axis Renderer以及Date Formatter:
            chart.setXAxisRenderer(new DateXAxisRenderer(chart.getViewPortHandler(), chart.getXAxis(), chart.getTransformer(null)));
            chart.getXAxis().setValueFormatter(new ValueFormatter() {
                @Override
                public String getFormattedValue(float value) {
                    if ((int) value / XSCALE_ONE_DAY * XSCALE_ONE_DAY == value)
                        return xAxisDataFormat_DD_MMM.format(new Date((long) value * MS_PER_XSCALE - TIMEOFFSET));
                    else
                        return xAxisDataFormat_DD_MMM_H.format(new Date((long) value  * MS_PER_XSCALE - TIMEOFFSET));
                }
            });
    
    1. 如下实现日期轴渲染器:
     class DateXAxisRenderer extends XAxisRenderer {
            public DateXAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) {
                super(viewPortHandler, xAxis, trans);
            }
    
            @Override
            protected void computeAxisValues(float min, float max) {
                int day_fraction[] = {1,2,3,4,6,8,12,24};
                float interval=0;
                int labelCount=0;
                float xMin = min;
                float xMax = max;
    
                xMax -= xMax % XSCALE_ONE_DAY;
                xMin += XSCALE_ONE_DAY - (xMin % XSCALE_ONE_DAY);
                int days = (int) ((xMax - xMin) / XSCALE_ONE_DAY);
                float days_interval = days / 3;
                if (days_interval > 0) {
                    interval = days_interval * XSCALE_ONE_DAY;
                    labelCount = (int) ((xMax - xMin) / interval);
                }
    
                if (days_interval == 0 || labelCount<3) {
                    int i = day_fraction.length-1;
                    do {
                        xMax = max - max % (XSCALE_ONE_DAY / day_fraction[i]);
                        xMin = min + (XSCALE_ONE_DAY / day_fraction[i] - (min % (XSCALE_ONE_DAY / day_fraction[i])));
                        labelCount = (int) ((xMax - xMin) / (XSCALE_ONE_DAY / day_fraction[i]));
                    } while (labelCount > 4 && i-- > 0);
                    interval = (xMax - xMin) / labelCount;
                }
    
                if (labelCount == 0 /*|| range <= 0 || Double.isInfinite(range)*/) {
                    mAxis.mEntries = new float[]{};
                    mAxis.mCenteredEntries = new float[]{};
                    mAxis.mEntryCount = 0;
                    return;
                }
    
                labelCount++;   // add last label
                //Timber.i("corrected min:" + xMin + ", max:" + xMax + ", interval:" + interval + ", labelcount:" + labelCount);
    
                mAxis.mEntries = new float[labelCount];
                float v = xMin;
                for (int i = 0; i < labelCount; i++) {
                    mAxis.mEntries[i] = v;
                    Timber.i("Label " + i + " at:" + mAxis.mEntries[i] + " day:" + mAxis.mEntries[i] / XSCALE_ONE_DAY);
                    v += interval;
                }
    
                //mAxis.setLabelCount(labelCount);
                //mAxis.setGranularityEnabled(false);
                mAxis.mEntryCount = labelCount;
            }
        }
    

    就是这样!

    备注:很好地呈现的范围是几天到几分钟,但我需要几年、几个月或几秒钟,你必须相应地调整格式化程序以及实现的 computeAxisValues()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-25
      • 2015-02-03
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多