目的
MSingleColumnStackBarChart
类被设计用于创建只有单列的堆叠柱状图,用于血糖数据的统计。以下是封装这个类的目的的详细描述:
- 抽象复杂性: 通过创建
MSingleColumnStackBarChart
类,你将复杂的MPAndroidChart库的使用和配置封装在一个独立的类中。这有助于降低代码的复杂性,使得在其他部分的代码中更容易理解和维护。 - 提高可读性: 将与图表配置相关的代码集中在一个类中,使得主要的业务逻辑部分的代码更加清晰。其他开发者在查看代码时能够更轻松地理解图表的配置和使用方式。
- 重用性: 通过封装这个类,你可以在不同的部分或项目中重复使用相同的图表配置。这意味着,如果将来有其他地方需要显示类似的单列堆叠柱状图,你可以轻松地引入这个类,而无需重新实现相同的配置。
- 模块化: 类的封装使得代码更加模块化。这允许你将图表的配置和数据处理与其他功能分离,促使代码更易于组织和维护。
- 简化调用: 通过提供简单的接口,类的使用者只需几行代码就能创建和显示单列堆叠柱状图。这有助于降低使用图表功能时的学习曲线,并使代码更加整洁。
总体而言,MSingleColumnStackBarChart
类的封装旨在提供一种简单、灵活且易于使用的方式,以满足特定场景下(如血糖数据统计)显示单列堆叠柱状图的需求。这样的封装是为了在开发中提高效率、降低出错概率,并促使代码更具可维护性。
示例
中间的就是柱状形,只要按百分比进行堆叠显示。
调用示例
List<MSingleColumnStackBarChart.MBarData> dataList = new ArrayList<>();
for (int x = 0; x < 1; x++) {
MSingleColumnStackBarChart.MBarData data = new MSingleColumnStackBarChart.MBarData(15, getColor(R.color.colorHHigh), "15% 很高 > 13.0 mmol/L");
dataList.add(data);
data = new MSingleColumnStackBarChart.MBarData(10, getColor(R.color.colorHigh), "10% 偏高 > 10.0 mmol/L");
dataList.add(data);
data = new MSingleColumnStackBarChart.MBarData(60, getColor(R.color.colorNormal), "60% 正常 3.9-10.0 mmol/L");
dataList.add(data);
data = new MSingleColumnStackBarChart.MBarData(10, getColor(R.color.colorLow), "10% 偏低 < 3.9 mmol/L");
dataList.add(data);
data = new MSingleColumnStackBarChart.MBarData(5, getColor(R.color.colorLLow), "5% 很低 < 3.0 mmol/L ");
dataList.add(data);
}
BarChart barChart = findViewById(R.id.bar_chart);
MSingleColumnStackBarChart barChartView = new MSingleColumnStackBarChart(barChart);
barChartView.setBarDataSets(dataList);
完整的代码实现类
package com.jaredrummler.compent;
import android.graphics.Color;
import android.graphics.PointF;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.LegendEntry;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.formatter.ValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* author :hello
* date : 2024/1/15 8:47
* description : 只有一列数据的StackBarChart
*/
public class MSingleColumnStackBarChart {
private BarChart barChart;
private MLegend mLegend;
public MSingleColumnStackBarChart(BarChart barChart) {
this.barChart = barChart;
this.mLegend = new MLegend();
init();
}
public void setBarDataSets(List<MBarData> dataList) {
MBarDataSet barDataSet = new MBarDataSet(0, dataList);
BarData barData = new BarData(barDataSet.getBarDataSet());
barData.setBarWidth(.8f);
this.barChart.setData(barData);
this.mLegend.setLegendConfig(barDataSet.getBarDataSetsColors(), barDataSet.getBarLegendLabels().toArray(new String[0]));
this.barChart.invalidate();
}
public void init() {
setXAxisConfig();
setYAxisConfig();
///所有值均绘制在其条形顶部上方
barChart.setDrawValueAboveBar(false);
// 添加下面这行代码,关闭堆叠模式
barChart.setDrawBarShadow(false);
barChart.setFitBars(true);
barChart.getDescription().setEnabled(false);
barChart.animateXY(1000,1000);
//选中高亮显示
barChart.setHighlightFullBarEnabled(false);
//双击缩放
barChart.setDoubleTapToZoomEnabled(false);
// 设置 是否可以缩放
barChart.setScaleEnabled(false);
barChart.setDrawGridBackground(false);
barChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, Highlight h) {
mLegend.showLegendSelected(h.getStackIndex());
}
@Override
public void onNothingSelected() {
mLegend.resetLegendDefault();
}
});
barChart.invalidate(); // 刷新图表
}
private void setXAxisConfig() {
// 使柱状图的中心与 X 轴标签对齐
XAxis xAxis = barChart.getXAxis();
xAxis.setEnabled(false);
xAxis.setDrawLabels(false);
//取消 垂直 网格线
xAxis.setDrawGridLines(false);
}
private void setYAxisConfig() {
YAxis yLeftAxis = barChart.getAxisLeft();
yLeftAxis.setEnabled(false);
yLeftAxis.setDrawLabels(false);
yLeftAxis.setDrawGridLines(false);
yLeftAxis.setAxisMinimum(0);
yLeftAxis.setAxisMaximum(100);
YAxis yRightAxis = barChart.getAxisRight();
yRightAxis.setEnabled(false);
yRightAxis.setDrawLabels(false);
yRightAxis.setDrawGridLines(false);
}
private static class MBarDataSet {
private BarDataSet barDataSet;
private List<BarEntry> barEntries;
private List<MBarData> dataList;
public MBarDataSet(int index, List<MBarData> dataList) {
this.dataList = dataList;
barEntries = covertToBarEntry(index, dataList);
barDataSet = new BarDataSet(barEntries, "");
barDataSet.setColors(dataList.stream().map(MBarData::getColor).collect(Collectors.toList()));
// barDataSet.setValueTextSize(10f);
barDataSet.setDrawValues(false);
// barDataSet.setValueTextColor(Color.WHITE);
// barDataSet.setValueFormatter(new ValueFormatter() {
// @Override
// public String getFormattedValue(float value) {
// return String.format("%.1f", value) + "%";
// }
//
// }); // 设置值文本的位置为外部
barDataSet.setBarShadowColor(Color.WHITE);
barDataSet.setBarBorderWidth(2f);
barDataSet.setBarBorderColor(Color.WHITE);
}
public BarDataSet getBarDataSet() {
return barDataSet;
}
public List<BarEntry> getBarEntries() {
return barEntries;
}
private List<BarEntry> covertToBarEntry(float index, List<MBarData> dataList) {
// y 数据
ArrayList<BarEntry> yValues = new ArrayList<>();
float[] stackedValues = new float[dataList.size()];
// 遍历 yourDataList,获取每个数据项的百分比值,构建堆叠数据
for (int i = 0; i < dataList.size(); i++) {
float yValue = dataList.get(i).getYValue();
stackedValues[i] = yValue;
}
BarEntry barEntry = new BarEntry(index, stackedValues);
yValues.add(barEntry);
return yValues;
}
private List<Integer> getBarDataSetsColors() {
List<Integer> barColors = new ArrayList<>();
for (MBarData data : this.dataList) {
barColors.add(data.getColor());
}
return barColors;
}
private List<String> getBarLegendLabels() {
List<String> legendLabels = new ArrayList<>();
for (MBarData data : this.dataList) {
legendLabels.add(data.getLabel());
}
return legendLabels;
}
}
public static class MBarData {
private float yValue;
private int color;
private String label;
public MBarData(float percentage, int color, String label) {
this.yValue = percentage;
this.color = color;
this.label = label;
}
public float getYValue() {
return yValue;
}
public int getColor() {
return color;
}
public String getLabel() {
return label;
}
}
private class MLegend {
public static final float SELECTED_FORM_SIZE = 16f;
public static final float DEFAULT_FORM_SIZE = 10f;
public void showLegendSelected(int index) {
// 选中时突出显示相应的 Legend 标签
// 获取 Legend 对象
Legend legend = barChart.getLegend();
// 获取当前 Legend 的条目
LegendEntry[] entries = legend.getEntries();
for (int i = 0; i < entries.length; i++) {
if (i == index) {
entries[index].formSize = SELECTED_FORM_SIZE;
} else {
entries[i].formSize = DEFAULT_FORM_SIZE;
}
}
// 刷新图表
barChart.invalidate();
}
public void resetLegendDefault() {
// 获取当前 Legend 的条目
// 获取 Legend 对象
Legend legend = barChart.getLegend();
LegendEntry[] entries = legend.getEntries();
for (int i = 0; i < entries.length; i++) {
entries[i].formSize = DEFAULT_FORM_SIZE;
}
barChart.invalidate();
}
public void setLegendConfig(List<Integer> barColors, String[] legendLabels) {
Legend legend = barChart.getLegend();
legend.setFormToTextSpace(8f);
legend.setStackSpace(16f);
legend.setForm(Legend.LegendForm.CIRCLE);
legend.setTextSize(14f);
YAxis yAxis = barChart.getAxisLeft();
float spaceTop = yAxis.getSpaceTop();
float spaceBottom = yAxis.getSpaceBottom();
float yAxisHeight = yAxis.getAxisMaximum() - spaceTop - spaceBottom;
legend.setYEntrySpace(yAxisHeight / (legendLabels.length));
legend.setYOffset(spaceTop);
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
legend.setOrientation(Legend.LegendOrientation.VERTICAL);
legend.setStackSpace(1f);
legend.setDrawInside(false);
if (legendLabels != null && legendLabels.length > 0) {
List<LegendEntry> legendEntries = new ArrayList<>();
for (int i = 0; i < legendLabels.length; i++) {
LegendEntry entry = new LegendEntry();
entry.label = legendLabels[i];
entry.formColor = barColors.get(i);
entry.formSize = 10f;
legendEntries.add(entry);
}
legend.setCustom(legendEntries);
}
}
}
}