使用 MPAndroidChart 在条形图中的时间轴轴上绘制数据值
Plot data value on Timeline axis in Bar chart using MPAndroidChart
我想在类似于 iOS 的“健康”应用的 Android 应用中绘制条形图。
这是屏幕截图。
我尝试使用 MPAndroidChart 绘图。
我看过该库中给出的示例,但无法按照我的要求绘制。
我能够显示 1 年图表的条形图(第 2 个屏幕截图),因为它有 12 个数据点和 12 个 x 轴标签。
但是对于一日图,需要在x轴的2个标签之间显示条形。
也不明白我是如何在 x 轴上绘制 24 小时或任何其他时间长度及其值的。
有什么方法可以根据选定的选项卡将 X 轴设为时间轴或日期轴?
X 轴标签将根据当前日期和时间动态变化。所以我不能设置固定的字符串数组,还需要映射值和 x 轴时序。
谁能帮忙画一下数据和时间轴?
您可以用与绘制月份相同的方式绘制日期时间,但您将拥有 24 个值而不是 12 个值(每次一个值)。唯一的区别是时间图只有 4 X-labels 而不是几个月的 12 个,并且它呈现时间:仅上午 12 点、上午 6 点、中午 12 点、下午 6 点,所有其他时间标签均为空值。
下面我将通过代码示例描述如何绘制和映射每个 Y-Value 及其对应的 X-Label:
1.Add BarChart
变成 Activity xml 布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/barChart"
android:layout_width="match_parent"
android:layout_height="300dp" />
</RelativeLayout>
2.Get 对条形图的引用
mBarChart = findViewById(R.id.barChart);
3.Plot 使用以下函数的月份图表:
private void showMonthsBars(){
//input Y data (Months Data - 12 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)1800);
valuesList.add((double)1600);
valuesList.add((double)500);
valuesList.add((double)1500);
valuesList.add((double)900);
valuesList.add((double)1700);
valuesList.add((double)400);
valuesList.add((double)2000);
valuesList.add((double)2500);
valuesList.add((double)3500);
valuesList.add((double)3000);
valuesList.add((double)1800);
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize x Axis Labels (labels for 13 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
xAxisLabel.add("J"); //this label will be mapped to the 1st index of the valuesList
xAxisLabel.add("F");
xAxisLabel.add("M");
xAxisLabel.add("A");
xAxisLabel.add("M");
xAxisLabel.add("J");
xAxisLabel.add("J");
xAxisLabel.add("A");
xAxisLabel.add("S");
xAxisLabel.add("O");
xAxisLabel.add("N");
xAxisLabel.add("D");
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(xAxisLabel.size(), true); //draw x labels for 13 vertical grid lines
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
xAxis.setCenterAxisLabels(true);
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(6000f);
rightAxis.setLabelCount(4, true); //draw y labels (Y-Values) for 4 horizontal grid lines starting from 0 to 6000f (step=2000)
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Months");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.invalidate();
}
或像下面这样绘制一天的 24 小时:
private void showDayHoursBars(){
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
for(int i = 0; i < 24; i++){
switch (i){
case 0:
xAxisLabel.add("12 AM"); //12AM - 5AM
break;
case 6:
xAxisLabel.add("6"); //6AM - 11AM
break;
case 12:
xAxisLabel.add("12 PM"); //12PM - 5PM
break;
case 18:
xAxisLabel.add("6"); //6PM - 11PM
break;
default:
xAxisLabel.add(String.format(Locale.US, "%02d", i)+":00");
break;
}
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(5, true); //show only 5 labels (5 vertical grid lines)
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
//xAxis.setCenterAxisLabels(true); //don't center the x labels as we are using a custom XAxisRenderer to set the label x, y position
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(1500f);
rightAxis.setLabelCount(4, true); //labels (Y-Values) for 4 horizontal grid lines
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Hours");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
@Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
//for 6AM and 6PM set the correct label x position based on your needs
if(!TextUtils.isEmpty(formattedLabel) && formattedLabel.equals("6"))
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
//for 12AM and 12PM set the correct label x position based on your needs
else
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(20f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
}
});
mBarChart.invalidate();
}
从上面的示例中,我使用了一些虚拟数据来显示 Y-Values 和 X-Values 之间的映射。 Month-Chart 和 Day-Chart 之间的一个主要区别是,在 Month-Chart 中,我使用 xAxis.setCenterAxisLabels(true);
将 x-labels 在每个 Bar 中居中,而在 Day-Chart 中,我已根据您的屏幕截图使用自定义 XAxisRenderer
将每个标签对齐到正确的 x,y 位置。
以下是上述代码的结果:
Months-BarChart:
DayHours-BarChart:
注意:这是用 com.github.PhilJay:MPAndroidChart:v3.1.0
测试的。
映射 X-Axis 时间戳与 Y-Value 的示例:
如果您已经有了 X-Axis 的时间戳,您可以将它们转换为适当的字符串标签值,该值将映射到 Y-Data 值的相应索引。
下面是一个示例,说明如何从时间戳开始绘制 Times-Graph,例如:27-02-2022 16:00。在这里,我使用 cal.setTimeInMillis()
将时间戳转换为日历对象,然后我使用此日历使用 cal.add(Calendar.HOUR_OF_DAY, 1);
获取循环中的新小时,该 cal.add(Calendar.HOUR_OF_DAY, 1);
用作 [=111 中的时间标签=] 以您希望在 X-Axis 中显示的格式喜欢 String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase();
。每个 Y-Data 值对应于 X-Axis 的适当索引。下面的例子从下午 4 点开始到下午 3 点来处理一天的 24 小时:
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//in case you already have the timestamp for a day then do the following:
//convert the timestamp to calendar by using the cal.setTimeInMillis() and then use the Calendar to iterate the 24H using the cal.add(Calendar.HOUR_OF_DAY, 1);
//like the below example:
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
//convert the above timestamp to Calendar using the cal.setTimeInMillis()
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
//this is the day from the above Calendar
String day = DateFormat.format("dd-MM-yyyy HH:mm", cal).toString(); //this is: 27-02-2022 16:00
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
//iterate all 24 hours to add the label for each time
for(int i = 0; i < 24; i++){
//get current hour in format "hh a" which is eg: 12 AM, 01 AM, etc..
String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase();
//get the hour 0-11 AM or 0-11 PM
int hour = cal.get(Calendar.HOUR);
//check if the above hour is AM or PM (0=AM, 1=PM)
int amPm = cal.get(Calendar.AM_PM);
//this is the current TimeStamp for the current working hour in the loop:
long timeStamp = cal.getTimeInMillis();
//add the dayHour String as the label you want to display in xAxis
xAxisLabel.add(dayHour); //this will be mapped to the corresponding index of the valuesList (Y-Data List)
//increment the Calendar.HOUR_OF_DAY plus +1 to go to the next hour in 24H format
cal.add(Calendar.HOUR_OF_DAY, 1);
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
完整代码如下:
private void showDayHoursBars() {
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//in case you already have the timestamp for a day then do the following:
//convert the timestamp to calendar by using the cal.setTimeInMillis() and then use the Calendar to iterate the 24H using the cal.add(Calendar.HOUR_OF_DAY, 1);
//like the below example:
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
//convert the above timestamp to Calendar using the cal.setTimeInMillis()
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
//this is the day from the above Calendar
String day = DateFormat.format("dd-MM-yyyy HH:mm", cal).toString(); //this is: 27-02-2022 16:00
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
//iterate all 24 hours to add the label for each time
for(int i = 0; i < 24; i++){
//get current hour in format "hh a" which is eg: 12 AM, 01 AM, etc..
String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase();
//get the hour 0-11 AM or 0-11 PM
int hour = cal.get(Calendar.HOUR);
//check if the above hour is AM or PM (0=AM, 1=PM)
int amPm = cal.get(Calendar.AM_PM);
//this is the current TimeStamp for the current working hour in the loop:
long timeStamp = cal.getTimeInMillis();
//add the dayHour String as the label you want to display in xAxis
xAxisLabel.add(dayHour); //this will be mapped to the corresponding index of the valuesList (Y-Data List)
//increment the Calendar.HOUR_OF_DAY plus +1 to go to the next hour in 24H format
cal.add(Calendar.HOUR_OF_DAY, 1);
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(5, true); //show only 5 labels (5 vertical grid lines)
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
//xAxis.setCenterAxisLabels(true); //don't center the x labels as we are using a custom XAxisRenderer to set the label x, y position
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(1500f);
rightAxis.setLabelCount(4, true); //labels (Y-Values) for 4 horizontal grid lines
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Hours");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
@Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
//for 6AM and 6PM set the correct label x position based on your needs
if(!TextUtils.isEmpty(formattedLabel) && formattedLabel.equals("6"))
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
//for 12AM and 12PM set the correct label x position based on your needs
else
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(20f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
}
});
mBarChart.invalidate();
}
这是新的结果(下午 4 点到下午 3 点):
示例 2 映射 X-Axis 具有 Y-Values 的时间戳:
下面是另一个示例,说明如何将 X(时间戳)映射到 Y(值):
//prepare X,Y data
ArrayList<Double> valuesList = new ArrayList<Double>();
ArrayList<Long> xAxisLabel = new ArrayList<>();
for(int i = 0; i < 24; i++){
valuesList.add((double)100+i); //y-values
xAxisLabel.add(1645970400000L+i); //x-timestamps
}
xAxisLabel.add(0L); //empty x for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
并且根据上面的映射,您可以使用 setLabelCount
在 X-Axis 上呈现您希望的标签数量。例如:使用 xAxis.setLabelCount(xAxisLabel.size(), true);
您可以呈现 X-axis.
中的所有标签
回调 getFormattedValue(float value)
每次特定的 X-index 准备好在图形上呈现时都会被调用,因此您必须首先获取索引,然后您可以从中获取正确的时间戳如下例所示:
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.setLabelCount(xAxisLabel.size(), true); //show all the labels
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
int xIndex = (int) value;
if(xIndex == xAxisLabel.size()-1)
return "";
Long timeStamp = xAxisLabel.get(xIndex);
//here convert the timestamp to the appropriate String value
return String.valueOf(timeStamp);
}
});
下面是基于上述示例的所有标签的 X-Timestamps 结果。为了呈现如下图所示的标签,我还进行了以下更改:
xAxis.setLabelRotationAngle(90); //this rotates the x labels to 90 degrees
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
@Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y, mAxisLabelPaint, anchor, angleDegrees);
}
});
时间戳结果:
X-Timestamps 每 10 秒水平滚动一次。每页有 10 个时间戳。
下面我将展示如何修改上述代码以处理 X-Y 映射以每 10 秒显示 X-Timestamps 的要点:
int visibleXValuesPerPage = 10;
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
ArrayList<Double> valuesList = new ArrayList<Double>();
ArrayList<Long> xAxisLabel = new ArrayList<>();
//1h = 3600 seconds
//1d = 86400 seconds
//1w = 604800 seconds
int seconds = 3600;
//the loop here is incremented by 10 seconds (i+=10)
for(int i = 0; i < seconds; i+=10){
String time = DateFormat.format("dd-MM-yyyy HH:mm:ss", cal).toString();
long timeStamp = cal.getTimeInMillis();
valuesList.add((double)i);
xAxisLabel.add(timeStamp);
cal.add(Calendar.SECOND, 10);
}
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue());
entries.add(barEntry);
}
XAxis xAxis = mBarChart.getXAxis();
xAxis.setAxisMinimum(0 + 0.5f);
xAxis.setAxisMaximum(entries.size() + 0.5f);
xAxis.setLabelCount(visibleXValuesPerPage, false);
xAxis.setLabelRotationAngle(90);
xAxis.setCenterAxisLabels(true);
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
if (value >= 0)
{
int xIndex = (int)value;
if (value > xAxisLabel.size()-1 && value <= xAxisLabel.size())
return "";
if (xIndex < xAxisLabel.size())
{
Long timeStamp = xAxisLabel.get(xIndex);
//here convert the timestamp to the appropriate String value
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timeStamp);
String time = DateFormat.format("dd-MM-yyyy HH:mm:ss", cal).toString();
return String.valueOf(time);
}
return "";
}
return "";
}
});
//set the BarData to chart
mBarChart.setVisibleXRangeMaximum(visibleXValuesPerPage);
mBarChart.invalidate();
我想在类似于 iOS 的“健康”应用的 Android 应用中绘制条形图。
这是屏幕截图。
我尝试使用 MPAndroidChart 绘图。 我看过该库中给出的示例,但无法按照我的要求绘制。
我能够显示 1 年图表的条形图(第 2 个屏幕截图),因为它有 12 个数据点和 12 个 x 轴标签。 但是对于一日图,需要在x轴的2个标签之间显示条形。
也不明白我是如何在 x 轴上绘制 24 小时或任何其他时间长度及其值的。
有什么方法可以根据选定的选项卡将 X 轴设为时间轴或日期轴? X 轴标签将根据当前日期和时间动态变化。所以我不能设置固定的字符串数组,还需要映射值和 x 轴时序。 谁能帮忙画一下数据和时间轴?
您可以用与绘制月份相同的方式绘制日期时间,但您将拥有 24 个值而不是 12 个值(每次一个值)。唯一的区别是时间图只有 4 X-labels 而不是几个月的 12 个,并且它呈现时间:仅上午 12 点、上午 6 点、中午 12 点、下午 6 点,所有其他时间标签均为空值。 下面我将通过代码示例描述如何绘制和映射每个 Y-Value 及其对应的 X-Label:
1.Add BarChart
变成 Activity xml 布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/barChart"
android:layout_width="match_parent"
android:layout_height="300dp" />
</RelativeLayout>
2.Get 对条形图的引用
mBarChart = findViewById(R.id.barChart);
3.Plot 使用以下函数的月份图表:
private void showMonthsBars(){
//input Y data (Months Data - 12 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)1800);
valuesList.add((double)1600);
valuesList.add((double)500);
valuesList.add((double)1500);
valuesList.add((double)900);
valuesList.add((double)1700);
valuesList.add((double)400);
valuesList.add((double)2000);
valuesList.add((double)2500);
valuesList.add((double)3500);
valuesList.add((double)3000);
valuesList.add((double)1800);
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize x Axis Labels (labels for 13 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
xAxisLabel.add("J"); //this label will be mapped to the 1st index of the valuesList
xAxisLabel.add("F");
xAxisLabel.add("M");
xAxisLabel.add("A");
xAxisLabel.add("M");
xAxisLabel.add("J");
xAxisLabel.add("J");
xAxisLabel.add("A");
xAxisLabel.add("S");
xAxisLabel.add("O");
xAxisLabel.add("N");
xAxisLabel.add("D");
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(xAxisLabel.size(), true); //draw x labels for 13 vertical grid lines
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
xAxis.setCenterAxisLabels(true);
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(6000f);
rightAxis.setLabelCount(4, true); //draw y labels (Y-Values) for 4 horizontal grid lines starting from 0 to 6000f (step=2000)
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Months");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.invalidate();
}
或像下面这样绘制一天的 24 小时:
private void showDayHoursBars(){
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
for(int i = 0; i < 24; i++){
switch (i){
case 0:
xAxisLabel.add("12 AM"); //12AM - 5AM
break;
case 6:
xAxisLabel.add("6"); //6AM - 11AM
break;
case 12:
xAxisLabel.add("12 PM"); //12PM - 5PM
break;
case 18:
xAxisLabel.add("6"); //6PM - 11PM
break;
default:
xAxisLabel.add(String.format(Locale.US, "%02d", i)+":00");
break;
}
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(5, true); //show only 5 labels (5 vertical grid lines)
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
//xAxis.setCenterAxisLabels(true); //don't center the x labels as we are using a custom XAxisRenderer to set the label x, y position
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(1500f);
rightAxis.setLabelCount(4, true); //labels (Y-Values) for 4 horizontal grid lines
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Hours");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
@Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
//for 6AM and 6PM set the correct label x position based on your needs
if(!TextUtils.isEmpty(formattedLabel) && formattedLabel.equals("6"))
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
//for 12AM and 12PM set the correct label x position based on your needs
else
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(20f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
}
});
mBarChart.invalidate();
}
从上面的示例中,我使用了一些虚拟数据来显示 Y-Values 和 X-Values 之间的映射。 Month-Chart 和 Day-Chart 之间的一个主要区别是,在 Month-Chart 中,我使用 xAxis.setCenterAxisLabels(true);
将 x-labels 在每个 Bar 中居中,而在 Day-Chart 中,我已根据您的屏幕截图使用自定义 XAxisRenderer
将每个标签对齐到正确的 x,y 位置。
以下是上述代码的结果:
Months-BarChart:
DayHours-BarChart:
注意:这是用 com.github.PhilJay:MPAndroidChart:v3.1.0
测试的。
映射 X-Axis 时间戳与 Y-Value 的示例:
如果您已经有了 X-Axis 的时间戳,您可以将它们转换为适当的字符串标签值,该值将映射到 Y-Data 值的相应索引。
下面是一个示例,说明如何从时间戳开始绘制 Times-Graph,例如:27-02-2022 16:00。在这里,我使用 cal.setTimeInMillis()
将时间戳转换为日历对象,然后我使用此日历使用 cal.add(Calendar.HOUR_OF_DAY, 1);
获取循环中的新小时,该 cal.add(Calendar.HOUR_OF_DAY, 1);
用作 [=111 中的时间标签=] 以您希望在 X-Axis 中显示的格式喜欢 String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase();
。每个 Y-Data 值对应于 X-Axis 的适当索引。下面的例子从下午 4 点开始到下午 3 点来处理一天的 24 小时:
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//in case you already have the timestamp for a day then do the following:
//convert the timestamp to calendar by using the cal.setTimeInMillis() and then use the Calendar to iterate the 24H using the cal.add(Calendar.HOUR_OF_DAY, 1);
//like the below example:
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
//convert the above timestamp to Calendar using the cal.setTimeInMillis()
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
//this is the day from the above Calendar
String day = DateFormat.format("dd-MM-yyyy HH:mm", cal).toString(); //this is: 27-02-2022 16:00
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
//iterate all 24 hours to add the label for each time
for(int i = 0; i < 24; i++){
//get current hour in format "hh a" which is eg: 12 AM, 01 AM, etc..
String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase();
//get the hour 0-11 AM or 0-11 PM
int hour = cal.get(Calendar.HOUR);
//check if the above hour is AM or PM (0=AM, 1=PM)
int amPm = cal.get(Calendar.AM_PM);
//this is the current TimeStamp for the current working hour in the loop:
long timeStamp = cal.getTimeInMillis();
//add the dayHour String as the label you want to display in xAxis
xAxisLabel.add(dayHour); //this will be mapped to the corresponding index of the valuesList (Y-Data List)
//increment the Calendar.HOUR_OF_DAY plus +1 to go to the next hour in 24H format
cal.add(Calendar.HOUR_OF_DAY, 1);
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
完整代码如下:
private void showDayHoursBars() {
//input Y data (Day Hours - 24 Values)
ArrayList<Double> valuesList = new ArrayList<Double>();
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)270);
valuesList.add((double)430);
valuesList.add((double)110);
valuesList.add((double)30);
valuesList.add((double)200);
valuesList.add((double)180);
valuesList.add((double)0);
valuesList.add((double)140);
valuesList.add((double)160);
valuesList.add((double)0);
valuesList.add((double)100);
valuesList.add((double)0);
valuesList.add((double)750);
valuesList.add((double)1200);
valuesList.add((double)10);
valuesList.add((double)0);
//in case you already have the timestamp for a day then do the following:
//convert the timestamp to calendar by using the cal.setTimeInMillis() and then use the Calendar to iterate the 24H using the cal.add(Calendar.HOUR_OF_DAY, 1);
//like the below example:
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
//convert the above timestamp to Calendar using the cal.setTimeInMillis()
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
//this is the day from the above Calendar
String day = DateFormat.format("dd-MM-yyyy HH:mm", cal).toString(); //this is: 27-02-2022 16:00
//initialize x Axis Labels (labels for 25 vertical grid lines)
final ArrayList<String> xAxisLabel = new ArrayList<>();
//iterate all 24 hours to add the label for each time
for(int i = 0; i < 24; i++){
//get current hour in format "hh a" which is eg: 12 AM, 01 AM, etc..
String dayHour = DateFormat.format("hh a", cal).toString().toUpperCase();
//get the hour 0-11 AM or 0-11 PM
int hour = cal.get(Calendar.HOUR);
//check if the above hour is AM or PM (0=AM, 1=PM)
int amPm = cal.get(Calendar.AM_PM);
//this is the current TimeStamp for the current working hour in the loop:
long timeStamp = cal.getTimeInMillis();
//add the dayHour String as the label you want to display in xAxis
xAxisLabel.add(dayHour); //this will be mapped to the corresponding index of the valuesList (Y-Data List)
//increment the Calendar.HOUR_OF_DAY plus +1 to go to the next hour in 24H format
cal.add(Calendar.HOUR_OF_DAY, 1);
}
xAxisLabel.add(""); //empty label for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(14);
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setDrawGridLines(true);
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setAxisMinimum(0 + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setAxisMaximum(entries.size() + 0.5f); //to center the bars inside the vertical grid lines we need + 0.5 step
xAxis.setLabelCount(5, true); //show only 5 labels (5 vertical grid lines)
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setXOffset(0f); //labels x offset in dps
xAxis.setYOffset(0f); //labels y offset in dps
//xAxis.setCenterAxisLabels(true); //don't center the x labels as we are using a custom XAxisRenderer to set the label x, y position
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return xAxisLabel.get((int) value);
}
});
//initialize Y-Right-Axis
YAxis rightAxis = mBarChart.getAxisRight();
rightAxis.setTextColor(Color.BLACK);
rightAxis.setTextSize(14);
rightAxis.setDrawAxisLine(true);
rightAxis.setAxisLineColor(Color.BLACK);
rightAxis.setDrawGridLines(true);
rightAxis.setGranularity(1f);
rightAxis.setGranularityEnabled(true);
rightAxis.setAxisMinimum(0);
rightAxis.setAxisMaximum(1500f);
rightAxis.setLabelCount(4, true); //labels (Y-Values) for 4 horizontal grid lines
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
//initialize Y-Left-Axis
YAxis leftAxis = mBarChart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setDrawAxisLine(true);
leftAxis.setLabelCount(0, true);
leftAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return "";
}
});
//set the BarDataSet
BarDataSet barDataSet = new BarDataSet(entries, "Hours");
barDataSet.setColor(Color.RED);
barDataSet.setFormSize(15f);
barDataSet.setDrawValues(false);
barDataSet.setValueTextSize(12f);
//set the BarData to chart
BarData data = new BarData(barDataSet);
mBarChart.setData(data);
mBarChart.setScaleEnabled(false);
mBarChart.getLegend().setEnabled(false);
mBarChart.setDrawBarShadow(false);
mBarChart.getDescription().setEnabled(false);
mBarChart.setPinchZoom(false);
mBarChart.setDrawGridBackground(true);
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
@Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
//for 6AM and 6PM set the correct label x position based on your needs
if(!TextUtils.isEmpty(formattedLabel) && formattedLabel.equals("6"))
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
//for 12AM and 12PM set the correct label x position based on your needs
else
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(20f), y+Utils.convertDpToPixel(1f), mAxisLabelPaint, anchor, angleDegrees);
}
});
mBarChart.invalidate();
}
这是新的结果(下午 4 点到下午 3 点):
示例 2 映射 X-Axis 具有 Y-Values 的时间戳:
下面是另一个示例,说明如何将 X(时间戳)映射到 Y(值):
//prepare X,Y data
ArrayList<Double> valuesList = new ArrayList<Double>();
ArrayList<Long> xAxisLabel = new ArrayList<>();
for(int i = 0; i < 24; i++){
valuesList.add((double)100+i); //y-values
xAxisLabel.add(1645970400000L+i); //x-timestamps
}
xAxisLabel.add(0L); //empty x for the last vertical grid line on Y-Right Axis
//prepare Bar Entries
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue()); //start always from x=1 for the first bar
entries.add(barEntry);
}
并且根据上面的映射,您可以使用 setLabelCount
在 X-Axis 上呈现您希望的标签数量。例如:使用 xAxis.setLabelCount(xAxisLabel.size(), true);
您可以呈现 X-axis.
回调 getFormattedValue(float value)
每次特定的 X-index 准备好在图形上呈现时都会被调用,因此您必须首先获取索引,然后您可以从中获取正确的时间戳如下例所示:
//initialize xAxis
XAxis xAxis = mBarChart.getXAxis();
xAxis.setLabelCount(xAxisLabel.size(), true); //show all the labels
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
int xIndex = (int) value;
if(xIndex == xAxisLabel.size()-1)
return "";
Long timeStamp = xAxisLabel.get(xIndex);
//here convert the timestamp to the appropriate String value
return String.valueOf(timeStamp);
}
});
下面是基于上述示例的所有标签的 X-Timestamps 结果。为了呈现如下图所示的标签,我还进行了以下更改:
xAxis.setLabelRotationAngle(90); //this rotates the x labels to 90 degrees
mBarChart.setXAxisRenderer(new XAxisRenderer(mBarChart.getViewPortHandler(), mBarChart.getXAxis(), mBarChart.getTransformer(YAxis.AxisDependency.LEFT)){
@Override
protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) {
Utils.drawXAxisValue(c, formattedLabel, x+Utils.convertDpToPixel(5f), y, mAxisLabelPaint, anchor, angleDegrees);
}
});
时间戳结果:
X-Timestamps 每 10 秒水平滚动一次。每页有 10 个时间戳。
下面我将展示如何修改上述代码以处理 X-Y 映射以每 10 秒显示 X-Timestamps 的要点:
int visibleXValuesPerPage = 10;
//get a dummy TimeStamp for 27-02-2022 16:00
Date date = new Date();
long dateTimeStamp = 0;
try {
String strDate = "27-02-2022 16:00";
date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.US).parse(strDate);
if(date!=null) {
dateTimeStamp = date.getTime();
}
}catch (Exception e){}
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(dateTimeStamp);
ArrayList<Double> valuesList = new ArrayList<Double>();
ArrayList<Long> xAxisLabel = new ArrayList<>();
//1h = 3600 seconds
//1d = 86400 seconds
//1w = 604800 seconds
int seconds = 3600;
//the loop here is incremented by 10 seconds (i+=10)
for(int i = 0; i < seconds; i+=10){
String time = DateFormat.format("dd-MM-yyyy HH:mm:ss", cal).toString();
long timeStamp = cal.getTimeInMillis();
valuesList.add((double)i);
xAxisLabel.add(timeStamp);
cal.add(Calendar.SECOND, 10);
}
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < valuesList.size(); i++) {
BarEntry barEntry = new BarEntry(i+1, valuesList.get(i).floatValue());
entries.add(barEntry);
}
XAxis xAxis = mBarChart.getXAxis();
xAxis.setAxisMinimum(0 + 0.5f);
xAxis.setAxisMaximum(entries.size() + 0.5f);
xAxis.setLabelCount(visibleXValuesPerPage, false);
xAxis.setLabelRotationAngle(90);
xAxis.setCenterAxisLabels(true);
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
if (value >= 0)
{
int xIndex = (int)value;
if (value > xAxisLabel.size()-1 && value <= xAxisLabel.size())
return "";
if (xIndex < xAxisLabel.size())
{
Long timeStamp = xAxisLabel.get(xIndex);
//here convert the timestamp to the appropriate String value
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timeStamp);
String time = DateFormat.format("dd-MM-yyyy HH:mm:ss", cal).toString();
return String.valueOf(time);
}
return "";
}
return "";
}
});
//set the BarData to chart
mBarChart.setVisibleXRangeMaximum(visibleXValuesPerPage);
mBarChart.invalidate();