You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter fl_chart:如何在Horizontal BarChart条形上叠加标签?

解决Flutter Web中Horizontal BarChart标签溢出与布局优化问题

核心思路

通过自定义条形组件,将标签直接叠加在条形内部避免溢出,同时将数值固定右对齐,充分利用有限的仪表盘空间。

具体实现步骤

1. 禁用默认右侧标签,自定义条形内容

利用BarChartRodData的rodWidget属性,将条形、标签、数值整合为一个自定义组件,确保标签仅在条形范围内显示。

2. 标签叠加与溢出处理

将标签放在条形内部左侧,添加文本省略处理,避免过长标签撑破布局;数值通过对齐方式固定在条形右侧。

3. 适配Web端有限空间

结合LayoutBuilder根据可用宽度动态调整字体和条形尺寸,进一步优化空间利用。

完整代码示例

import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';

class CustomHorizontalBarChart extends StatelessWidget {
  const CustomHorizontalBarChart({super.key});

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      // 根据容器宽度动态调整参数
      builder: (context, constraints) {
        final fontSize = constraints.maxWidth < 450 ? 10 : 12;
        final barWidth = constraints.maxWidth < 450 ? 16 : 22;

        return BarChart(
          BarChartData(
            alignment: BarChartAlignment.spaceAround,
            maxY: 100,
            barTouchData: const BarTouchData(enabled: false),
            // 关闭不需要的轴标签,节省空间
            titlesData: FlTitlesData(
              rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
              topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
              bottomTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
              leftTitles: AxisTitles(
                sideTitles: SideTitles(
                  showTitles: true,
                  reservedSize: 60, // 预留左侧分类标签空间
                  getTitlesWidget: (value, meta) {
                    return Text(
                      '分类${value.toInt() + 1}',
                      style: TextStyle(fontSize: fontSize),
                    );
                  },
                ),
              ),
            ),
            borderData: const FlBorderData(show: false),
            barGroups: _buildBarGroups(fontSize, barWidth),
          ),
        );
      },
    );
  }

  List<BarChartGroupData> _buildBarGroups(double fontSize, double barWidth) {
    final chartData = [
      {'label': '流量', 'value': 25},
      {'label': '用户留存', 'value': 68},
      {'label': '转化漏斗', 'value': 12},
      {'label': '系统负载', 'value': 85},
    ];

    return chartData.asMap().entries.map((entry) {
      final index = entry.key;
      final item = entry.value;
      return BarChartGroupData(
        x: index,
        barRods: [
          BarChartRodData(
            toY: item['value'] as double,
            width: barWidth,
            color: Colors.blueAccent.shade400,
            // 自定义条形组件,整合标签和数值
            rodWidget: Stack(
              children: [
                // 基础条形背景
                Container(
                  width: double.infinity,
                  color: Colors.blueAccent.shade400,
                ),
                // 叠加在条形上的标签(左对齐,溢出时省略)
                Align(
                  alignment: Alignment.centerLeft,
                  child: Padding(
                    padding: const EdgeInsets.only(left: 6),
                    child: Text(
                      item['label'] as String,
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: fontSize,
                        fontWeight: FontWeight.w500,
                      ),
                      overflow: TextOverflow.ellipsis,
                      maxLines: 1,
                    ),
                  ),
                ),
                // 右对齐的数值
                Align(
                  alignment: Alignment.centerRight,
                  child: Padding(
                    padding: const EdgeInsets.only(right: 6),
                    child: Text(
                      '${item['value']}%',
                      style: TextStyle(
                        color: Colors.black87,
                        fontSize: fontSize,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      );
    }).toList();
  }
}

关键优化点说明

  • 标签溢出处理:通过TextOverflow.ellipsis限制标签仅显示一行,超出部分自动省略,避免布局溢出。
  • 数值固定对齐:使用Align将数值固定在条形右侧,无论条形长度如何,都能保持统一的右对齐样式。
  • 响应式适配:LayoutBuilder监听容器宽度,动态调整字体大小和条形宽度,适配Web端不同屏幕尺寸的仪表盘空间。

内容的提问来源于stack exchange,提问作者Steve3p0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:17:36