MPAndroidChart中如何设置X轴(时间)标签的固定间隔?
问题描述

我已经尝试了一周Stack Overflow上的各种方法,包括设置粒度、轴的最小与最大值。Y轴数值分布规整,间隔固定为40且末尾均为0,这是默认效果。我希望X轴也能实现类似分布,例如显示6个值:[11:20 11:30 11:40 11:50 12:00 12:10],缩放后可变为[11:20 11:25 11:30 11:35 11:40 11:45]。
现有代码
轴配置代码
XAxis xAxis = averageEventRateLineChart.getXAxis(); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(true); xAxis.setDrawGridLinesBehindData(false); xAxis.setAxisLineColor(mContext.getResources().getColor(R.color.graph_line_color)); xAxis.setTextSize(10f); xAxis.setAxisLineWidth(1f); xAxis.setTextColor(mContext.getResources().getColor(R.color.grey_text_color)); xAxis.setTypeface(ResourcesCompat.getFont(mContext, R.font.open_sans_regular)); xAxis.setValueFormatter(new MyValueFormatter()); YAxis leftAxis = averageEventRateLineChart.getAxisLeft(); leftAxis.setDrawGridLines(false); leftAxis.setDrawAxisLine(true); leftAxis.setDrawGridLinesBehindData(false); leftAxis.setAxisLineColor(mContext.getResources().getColor(R.color.graph_line_color)); leftAxis.setAxisLineWidth(1f); leftAxis.setAxisMinimum(0); leftAxis.setTextSize(10f); leftAxis.setTextColor(mContext.getResources().getColor(R.color.grey_text_color)); leftAxis.setTypeface(ResourcesCompat.getFont(mContext, R.font.open_sans_regular));
时间格式化类
public class MyValueFormatter extends ValueFormatter { private final SimpleDateFormat formatHours = new SimpleDateFormat("HH:mm", Locale.ENGLISH); private final SimpleDateFormat formatDays = new SimpleDateFormat("MMM d", Locale.ENGLISH); private final SimpleDateFormat formatMonths = new SimpleDateFormat("MMM yyyy", Locale.ENGLISH); public MyValueFormatter(LineChart lineChart) { } @Override public String getFormattedValue(float value) { long dataRange = (long) (mLineChart.getHighestVisibleX() - mLineChart.getLowestVisibleX()); if (dataRange < TimeUnit.HOURS.toMillis(24)) { return formatHours.format(new Date((long) value)); } else if (dataRange < TimeUnit.DAYS.toMillis(7)) { return formatDays.format(new Date((long) value)); } else { return formatMonths.format(new Date((long) value)); } } }
解决方案
要实现X轴按固定间隔(缩放时自动调整)显示规整刻度,可通过动态计算刻度间隔结合图表手势监听实现,具体步骤如下:
1. 配置X轴基础属性并添加监听
关闭自动刻度计算,开启粒度控制,并监听图表的缩放、滚动事件来实时更新刻度间隔:
XAxis xAxis = averageEventRateLineChart.getXAxis(); xAxis.setAvoidFirstLastClipping(true); xAxis.setGranularityEnabled(true); // 设置最小粒度为5分钟(对应毫秒值),确保间隔是5分钟的整数倍 xAxis.setGranularity(TimeUnit.MINUTES.toMillis(5)); // 禁用自动刻度数量计算,手动控制显示6个刻度 xAxis.setLabelCount(6, false); // 添加图表手势监听,触发刻度更新 averageEventRateLineChart.setOnChartGestureListener(new OnChartGestureListener() { @Override public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {} @Override public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { updateXAxisInterval(); } @Override public void onChartLongPressed(MotionEvent me) {} @Override public void onChartDoubleTapped(MotionEvent me) {} @Override public void onChartSingleTapped(MotionEvent me) {} @Override public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {} @Override public void onChartScale(MotionEvent me, float scaleX, float scaleY) { updateXAxisInterval(); } @Override public void onChartTranslate(MotionEvent me, float dX, float dY) {} }); // 初始化时执行一次刻度更新 updateXAxisInterval();
2. 实现动态计算刻度间隔的方法
根据当前可视范围计算合适的间隔,保证刻度规整且始终显示约6个值:
private void updateXAxisInterval() { XAxis xAxis = averageEventRateLineChart.getXAxis(); long visibleRange = (long) (averageEventRateLineChart.getHighestVisibleX() - averageEventRateLineChart.getLowestVisibleX()); int desiredLabelCount = 6; long fiveMinuteMillis = TimeUnit.MINUTES.toMillis(5); // 计算基础间隔,并向上取整为5分钟的整数倍 long interval = visibleRange / desiredLabelCount; interval = ((interval + fiveMinuteMillis - 1) / fiveMinuteMillis) * fiveMinuteMillis; // 设置粒度和刻度范围,确保起始刻度是间隔的整数倍 xAxis.setGranularity(interval); long startX = ((long) averageEventRateLineChart.getLowestVisibleX()) / interval * interval; xAxis.setAxisMinimum(startX); xAxis.setAxisMaximum(startX + interval * desiredLabelCount); }
3. 修复格式化类的初始化问题
原格式化类中mLineChart未初始化,需修正构造方法:
public class MyValueFormatter extends ValueFormatter { private final SimpleDateFormat formatHours = new SimpleDateFormat("HH:mm", Locale.ENGLISH); private final SimpleDateFormat formatDays = new SimpleDateFormat("MMM d", Locale.ENGLISH); private final SimpleDateFormat formatMonths = new SimpleDateFormat("MMM yyyy", Locale.ENGLISH); private final LineChart mLineChart; public MyValueFormatter(LineChart lineChart) { this.mLineChart = lineChart; } @Override public String getFormattedValue(float value) { long dataRange = (long) (mLineChart.getHighestVisibleX() - mLineChart.getLowestVisibleX()); if (dataRange < TimeUnit.HOURS.toMillis(24)) { return formatHours.format(new Date((long) value)); } else if (dataRange < TimeUnit.DAYS.toMillis(7)) { return formatDays.format(new Date((long) value)); } else { return formatMonths.format(new Date((long) value)); } } }
效果说明
- 缩放图表时,间隔会自动在5分钟、10分钟等5分钟的整数倍之间切换,保证刻度规整。
- 始终维持约6个刻度值,且刻度起始值为间隔的整数倍,实现和Y轴一致的规整分布。
内容的提问来源于stack exchange,提问作者Anon
相关产品推荐
相关产品推荐

