单列的堆叠柱状图

news2025/1/11 11:08:14
目的

MSingleColumnStackBarChart类被设计用于创建只有单列的堆叠柱状图,用于血糖数据的统计。以下是封装这个类的目的的详细描述:

  1. 抽象复杂性: 通过创建MSingleColumnStackBarChart类,你将复杂的MPAndroidChart库的使用和配置封装在一个独立的类中。这有助于降低代码的复杂性,使得在其他部分的代码中更容易理解和维护。

  2. 提高可读性: 将与图表配置相关的代码集中在一个类中,使得主要的业务逻辑部分的代码更加清晰。其他开发者在查看代码时能够更轻松地理解图表的配置和使用方式。

  3. 重用性: 通过封装这个类,你可以在不同的部分或项目中重复使用相同的图表配置。这意味着,如果将来有其他地方需要显示类似的单列堆叠柱状图,你可以轻松地引入这个类,而无需重新实现相同的配置。

  4. 模块化: 类的封装使得代码更加模块化。这允许你将图表的配置和数据处理与其他功能分离,促使代码更易于组织和维护。

  5. 简化调用: 通过提供简单的接口,类的使用者只需几行代码就能创建和显示单列堆叠柱状图。这有助于降低使用图表功能时的学习曲线,并使代码更加整洁。

总体而言,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);
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1388361.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

创意交融:集成自定义报表和仪表盘设计器,实现图标替换

前言 在现代数据分析领域&#xff0c;随着对报表和数据分析的需求不断增长&#xff0c;市场上涌现了许多嵌入式报表工具。这些工具能够与企业现有的OA、ERP、MES、CRM等应用系统深度集成&#xff0c;实现对业务数据的自助式分析。然而&#xff0c;在实际应用中&#xff0c;不同…

【量化交易实战记】小明的破晓时刻——2023下半年新能源汽车板块的成功掘金之旅

在2023年的炎炎夏日&#xff0c;小明在不断的观察分析市场的过程中&#xff0c;突然敏锐地察觉到了新能源汽车市场的风云变幻。他日复一日地研读行业报告、追踪政策动向、分析公司财报&#xff0c;以及密切关注全球市场动态。那段时间里&#xff0c;新能源汽车行业仿佛迎来了一…

Vue中父子组件通信

聚沙成塔每天进步一点点 本文内容 ⭐ 专栏简介Vue中父子组件通信1. Props父组件&#xff1a;子组件&#xff1a; 2. 自定义事件子组件&#xff1a;父组件&#xff1a; 3. 使用 v-model子组件&#xff1a;父组件&#xff1a; 4. 使用$refs子组件&#xff1a;父组件&#xff1a; …

必示科技助力中国联通智网创新中心通过智能化运维(AIOps)通用能力成熟度3级评估

2023年12月15日&#xff0c;中国信息通信研究院隆重公布了智能化运维AIOps系列标准最新批次评估结果。 必示科技与中国联通智网创新中心合作的“智能IT故障监控定位分析能力建设项目”通过了中国信息通信研究院开展的《智能化运维能力成熟度系列标准 第1部分&#xff1a;通用能…

通用外设-2.8‘TFT屏的使用

前言 一、验证连接是否正确 二、更改自己想用的图像 1.取模软件 Image2Lcd 2.9 的使用 2.使用 总结 前言 本文在中景园的代码上改写而来&#xff0c;主要记录下使用记录 一、验证连接是否正确 1.按内容说明进行线路连接 2.运行程序&#xff0c;因为内部有图片样本&…

这可能是最全面的Java并发编程八股文了

内容摘自我的学习网站&#xff1a;topjavaer.cn 分享50道Java并发高频面试题。 线程池 线程池&#xff1a;一个管理线程的池子。 为什么平时都是使用线程池创建线程&#xff0c;直接new一个线程不好吗&#xff1f; 嗯&#xff0c;手动创建线程有两个缺点 不受控风险频繁创…

23年全球数字经济发展如何?这本《白皮书》告诉你答案丨附下载

这一年&#xff0c;全球主要国家优化数字经济政策布局&#xff0c; 促进数字产业化创新升级、发展数字基础设施&#xff1b; 这一年&#xff0c;全域国际合作让“命运共同体” 构建见成效&#xff0c; 全球经济多极化趋势加强&#xff0c;中国坐拥Top1数字市场&#xff1b; …

第二证券:抢占技术前沿 中国光伏企业结伴“走出去”

2024年新年前后&#xff0c;光伏职业分外忙碌。据证券时报记者不完全统计&#xff0c;晶澳科技、华晟新动力、高测股份、华民股份等多家企业宣告新建项目投产&#xff0c;安徽皇氏绿能等企业的项目也迎来设备安装的重要节点。 证券时报记者采访多家企业的负责人后了解到&#…

js日期排序(使用sort)

根据日期进行排序&#xff0c;也可以根据number类型的大小来进行排序 按日期排序的函数 let data [{id: 2,time: 2019-04-26 10:53:19},{id: 4,time: 2019-04-26 10:51:19}, {id: 1,time: 2019-04-26 11:04:32}, {id: 3,time: 2019-04-26 11:05:32} ] //property是你需要排序…

一款好用的开源思维导图软件 docker部署教程

目录 Simple mind map简介 Simple mind map特点 1.拉取镜像 2.创建并启动容器 方式1&#xff1a;docker启动 方式2&#xff1a;docker compose启动 3.使用 4.源码地址 Simple mind map简介 .一个 Web 思维导图&#xff0c;基于思维导图库、Vue2.x、ElementUI 开发&#…

前端框架前置课Node.js学习(1) fs,path,模块化,CommonJS标准,ECMAScript标准,包

目录 什么是Node.js 定义 作用: 什么是前端工程化 Node.js为何能执行Js fs模块-读写文件 模块 语法: 1.加载fs模块对象 2.写入文件内容 3.读取文件内容 Path模块-路径处理 为什么要使用path模块 语法 URL中的端口号 http模块-创建Web服务 需求 步骤: 案例:浏…

geemap学习笔记048:光谱变换

前言 Earth Engine中有多种光谱变换方法。其中包括图像上的实例方法&#xff0c;例如 normalizedDifference()、unmix()、rgbToHsv() 和 hsvToRgb()。 1 导入库并初始化 import ee import geemapee.Initialize()2 全色图像锐化(Pan sharpening) Map geemap.Map(center[40,…

Java 使用 EasyExcel 爬取数据

一、爬取数据的基本思路 分析要爬取数据的来源 1. 查找数据来源&#xff1a;浏览器按 F12 或右键单击“检查”打开开发者工具查看数据获取时的请求地址 2. 查看接口信息&#xff1a;复制请求地址直接到浏览器地址栏输入看能不能取到数据 3. 推荐安装插件&#xff1a;FeHelper&a…

个人网站制作 Part 6 添加高级特性(页面动画、服务端集成) | Web开发项目

文章目录 &#x1f469;‍&#x1f4bb; 基础Web开发练手项目系列&#xff1a;个人网站制作&#x1f680; 添加页面动画&#x1f528;使用CSS动画&#x1f527;步骤 1: 添加动画效果 &#x1f528;使用JavaScript实现动画&#x1f527;步骤 2: 使用JavaScript添加动画 &#x1…

机器学习_梯度下降

文章目录 什么是梯度梯度下降梯度下降有什么用 什么是梯度 计算梯度向量其几何意义&#xff0c;就是函数变化的方向&#xff0c;而且是变化最快的方向。对于函数f(x)&#xff0c;在点(xo,yo)&#xff0c;梯度向量的方向也就是y值增加最快的方向。也就是说&#xff0c;沿着梯度…

常用界面设计组件 —— 窗体(QT)

二、常用界面设计组件2.1 窗体2.1.1 设置窗体位置、大小及背景颜色2.1.2 设置窗体标题2.1.3 多窗体调用 二、常用界面设计组件 组件是GUI的基本元素&#xff0c;也称为UI控件。它接受来自底层平台的不同用户事件&#xff0c;如鼠标和键盘事件&#xff08;以及其它事件&#xf…

初识 Elasticsearch 应用知识,一文读懂 Elasticsearch 知识文集(4)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

rpb/rpc文件说明与matlab读取

什么是rpb/rpc文件&#xff1f; rpb文件是用来存储用于遥感数据几何校正的RPC&#xff08;Rational Polynomial Coefficients &#xff09;模型的文件。类似的还有RPC文件&#xff0c;rpb与rpc文件只是格式不同&#xff0c;但包含的信息一致。其用于从图像坐标转换到地理坐标&a…

uint32无符号字节转为Java中的int

文章目录 前言一、无符号字节转为int1.前置知识2.无符号转int代码3.Java中字节转为int 二、字节缓冲流1.基础知识2.String与ByteBuffer转换 总结 前言 Java 中基本类型都是有符号数值&#xff0c;如果接收到了 C/C 处理的无符号数值字节流&#xff0c;将出现转码错误。 提示&a…

多线程——CAS

什么是CAS CAS的全称&#xff1a;Compare and swap&#xff0c;字面意思就是&#xff1a;“比较并交换”&#xff0c;一个CAS涉及到以下操作&#xff1a; 假设内存中的原数据V&#xff0c;旧的预期值A&#xff0c;需要修改的新值B 1.比较A与V是否相等&#xff08;比较&#xf…