柱状图无法正常填充指定颜色问题排查求助
柱状图无法填充颜色、显示为空的问题排查与修复
核心问题分析
- 日期格式不匹配:列表中的日期格式为
"23-5-2024"(日-月-年),但代码中用SimpleDateFormat("d.M.yy")格式化日期,得到的是"23.5.24",两者无法匹配,导致所有数据值都为0,柱状条高度为0,自然显示为空。 - 数据集无数据:
secondBarEntries从未添加任何BarEntry,对应的BarDataSet没有数据,不会渲染任何柱子。 - X轴范围与数据X值不匹配:你用时间戳(
date.time.toFloat())作为柱状条的X值,但X轴的范围被设置为-0.5f到3.5f,远小于时间戳数值,导致所有柱子都不在可视区域内。 - 分组柱状图逻辑错误:手动调整X值实现分组的方式错误,且重复向
firstBarEntries添加同X值的条目,造成数据混乱。
修复后的代码
private fun showEnergy() { val list = listOf( Triple("23-5-2024", 2010, 4.91), Triple("22-5-2024", 960, 13.62), Triple("21-5-2024", 5642, 2.0), Triple("20-5-2024", 1464, 4.85) ) constraintLayoutStatisticsData.removeAllViews() constraintLayoutStatisticsData.addView(energyLayout) barChart = constraintLayoutStatisticsData.findViewById(R.id.barChart) val maxValue = 10000f setupBarChart(maxValue) // 生成最近6天的日期,用统一格式匹配list中的数据 val currentDate = Date() val dates = ArrayList<Date>() val calendar = Calendar.getInstance() for (i in 0 until 6) { calendar.time = currentDate calendar.add(Calendar.DAY_OF_MONTH, -i) dates.add(calendar.time) } dates.reverse() val firstBarEntries = ArrayList<BarEntry>() val secondBarEntries = ArrayList<BarEntry>() val barWidth = 0.26f val groupSpace = 0.32f val barSpace = 0.08f // 改为和list匹配的日期格式:日-月-年 val dateFormat = SimpleDateFormat("d-M-yyyy", Locale.getDefault()) // 用索引作为X值,适配分组柱状图 for ((index, date) in dates.withIndex()) { val formattedDate = dateFormat.format(date) // 匹配list中的日期 val value = list.find { it.first == formattedDate }?.second ?: 0 // 第一组柱子用索引作为X值 firstBarEntries.add(BarEntry(index.toFloat(), value.toFloat())) // 第二组柱子添加数据,这里用示例值4000f,可根据需求替换 val value2 = 4000f secondBarEntries.add(BarEntry(index.toFloat(), value2.toFloat())) } val firstDataSet = BarDataSet(firstBarEntries, "") firstDataSet.color = ContextCompat.getColor(constraintLayoutStatisticsData.context, R.color.grey) firstDataSet.setDrawValues(false) val secondDataSet = BarDataSet(secondBarEntries, "") secondDataSet.setDrawValues(false) // 生成对应所有日期的颜色列表(6个条目) val customColors = mutableListOf<Int>() for (date in dates) { val formattedDate = dateFormat.format(date) val item = list.find { it.first == formattedDate } val ratio = item?.second?.div(4000f) ?: 0f val color = when { ratio >= 0.85 && ratio <= 1.15 -> ContextCompat.getColor(constraintLayoutStatisticsData.context, R.color.green) ratio < 0.85 -> ContextCompat.getColor(constraintLayoutStatisticsData.context, R.color.orange) else -> ContextCompat.getColor(constraintLayoutStatisticsData.context, R.color.red) } customColors.add(color) } secondDataSet.setColors(customColors) val dataSet = listOf(firstDataSet, secondDataSet) val barData = BarData(dataSet) barData.barWidth = barWidth // 设置分组柱状图的间距 val groupCount = dates.size barData.groupBars(0f, groupSpace, barSpace) val xAxis = barChart.xAxis // X轴范围适配分组后的宽度 xAxis.axisMinimum = 0f - barData.groupWidth(groupSpace, barSpace) / 2 xAxis.axisMaximum = (groupCount - 1) + barData.groupWidth(groupSpace, barSpace) / 2 xAxis.valueFormatter = object : ValueFormatter() { private val displayDateFormat = SimpleDateFormat("dd.MM", Locale.getDefault()) override fun getFormattedValue(value: Float): String { val index = value.toInt() return if (index >= 0 && index < dates.size) { displayDateFormat.format(dates[index]) } else { "" } } } barChart.axisLeft.valueFormatter = object : ValueFormatter() { override fun getFormattedValue(value: Float): String { return value.toInt().toString().replace(',', ' ') } } barChart.data = barData barChart.invalidate() } private fun setupBarChart(maxValue: Float) { barChart.setDrawBarShadow(false) barChart.description.isEnabled = false barChart.setMaxVisibleValueCount(60) barChart.setPinchZoom(false) barChart.setDrawGridBackground(false) val xAxis = barChart.xAxis xAxis.setDrawGridLines(false) xAxis.position = XAxis.XAxisPosition.BOTTOM xAxis.textColor = ContextCompat.getColor(constraintLayoutStatisticsData.context, R.color.text) xAxis.granularity = 1f val yAxisLeft = barChart.axisLeft yAxisLeft.setDrawAxisLine(false) yAxisLeft.textColor = ContextCompat.getColor(constraintLayoutStatisticsData.context, R.color.text) val minValue = 0f val labelCount = 5 val interval = Math.ceil((maxValue - minValue) / (labelCount - 1).toDouble()).toFloat() yAxisLeft.axisMinimum = minValue yAxisLeft.axisMaximum = maxValue yAxisLeft.setGranularity(interval) yAxisLeft.setLabelCount(labelCount, true) yAxisLeft.gridLineWidth = 2f barChart.axisRight.isEnabled = false barChart.legend.isEnabled = false }
关键修复点说明
- 统一了日期格式,确保list中的日期和格式化后的日期能正确匹配,获取到真实数据值;
- 填充了
secondBarEntries的数据集,确保第二个分组的柱子有数据可渲染; - 使用索引作为X值替代时间戳,配合
barData.groupBars实现正确的分组柱状图布局; - 调整了X轴的范围,确保所有柱子都在可视区域内;
- 生成了与日期数量匹配的颜色列表,避免颜色数量不足导致的渲染问题。
内容的提问来源于stack exchange,提问作者Liam Harpe
相关产品推荐
相关产品推荐

