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

Flutter实现堆叠柱状图可用哪些包?StackedColumn100Series无法自定义

Flutter 自定义堆叠柱状图实现方案

针对你想用Flutter创建指定样式堆叠柱状图,且使用StackedColumn100Series无法满足自定义需求的问题,提供两种可行方案:


方案一:优化Syncfusion的StackedColumn100Series配置

如果只是部分自定义需求未满足,可以通过扩展配置项实现,比如自定义颜色、标签、柱状图尺寸等:

import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:flutter/material.dart';

class CustomStackedBarChart extends StatelessWidget {
  final List<ChartData> chartData = [
    ChartData('Jan', 35, 28, 37),
    ChartData('Feb', 25, 30, 45),
    ChartData('Mar', 30, 25, 45),
    ChartData('Apr', 32, 22, 46),
  ];

  @override
  Widget build(BuildContext context) {
    return SfCartesianChart(
      primaryXAxis: CategoryAxis(
        labelStyle: TextStyle(color: Colors.grey[700], fontSize: 12),
        axisLine: const AxisLine(width: 0),
        majorTickLines: const MajorTickLines(width: 0),
      ),
      primaryYAxis: const NumericAxis(isVisible: false),
      series: _getStackedSeries(),
      legend: Legend(
        position: LegendPosition.bottom,
        iconHeight: 12,
        iconWidth: 12,
        textStyle: const TextStyle(fontSize: 12),
      ),
      tooltipBehavior: TooltipBehavior(enable: true),
    );
  }

  List<StackedColumn100Series<ChartData, String>> _getStackedSeries() {
    return [
      StackedColumn100Series<ChartData, String>(
        dataSource: chartData,
        xValueMapper: (ChartData data, _) => data.x,
        yValueMapper: (ChartData data, _) => data.y1,
        color: Colors.blue[300],
        dataLabelSettings: const DataLabelSettings(
          isVisible: true,
          labelAlignment: ChartDataLabelAlignment.middle,
          textStyle: TextStyle(fontSize: 10, color: Colors.white),
        ),
        width: 0.6,
      ),
      StackedColumn100Series<ChartData, String>(
        dataSource: chartData,
        xValueMapper: (ChartData data, _) => data.x,
        yValueMapper: (ChartData data, _) => data.y2,
        color: Colors.green[300],
        dataLabelSettings: const DataLabelSettings(
          isVisible: true,
          labelAlignment: ChartDataLabelAlignment.middle,
          textStyle: TextStyle(fontSize: 10, color: Colors.white),
        ),
        width: 0.6,
      ),
      StackedColumn100Series<ChartData, String>(
        dataSource: chartData,
        xValueMapper: (ChartData data, _) => data.x,
        yValueMapper: (ChartData data, _) => data.y3,
        color: Colors.orange[300],
        dataLabelSettings: const DataLabelSettings(
          isVisible: true,
          labelAlignment: ChartDataLabelAlignment.middle,
          textStyle: TextStyle(fontSize: 10, color: Colors.white),
        ),
        width: 0.6,
      ),
    ];
  }
}

class ChartData {
  ChartData(this.x, this.y1, this.y2, this.y3);
  final String x;
  final double y1;
  final double y2;
  final double y3;
}

方案二:完全自定义堆叠柱状图Widget

如果第三方库的配置无法实现你的特殊需求,可通过原生Widget手动构建,灵活性更高:

import 'package:flutter/material.dart';

class CustomStackedBar extends StatelessWidget {
  final List<Map<String, dynamic>> data = [
    {
      'label': 'Jan',
      'segments': [
        {'value': 35, 'color': Colors.blue[300]},
        {'value': 28, 'color': Colors.green[300]},
        {'value': 37, 'color': Colors.orange[300]},
      ]
    },
    {
      'label': 'Feb',
      'segments': [
        {'value': 25, 'color': Colors.blue[300]},
        {'value': 30, 'color': Colors.green[300]},
        {'value': 45, 'color': Colors.orange[300]},
      ]
    },
    {
      'label': 'Mar',
      'segments': [
        {'value': 30, 'color': Colors.blue[300]},
        {'value': 25, 'color': Colors.green[300]},
        {'value': 45, 'color': Colors.orange[300]},
      ]
    },
  ];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 图例
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            _buildLegendItem(Colors.blue[300]!, '系列1'),
            const SizedBox(width: 20),
            _buildLegendItem(Colors.green[300]!, '系列2'),
            const SizedBox(width: 20),
            _buildLegendItem(Colors.orange[300]!, '系列3'),
          ],
        ),
        const SizedBox(height: 20),
        // 柱状图主体
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: data.map((item) {
            return Column(
              children: [
                Container(
                  width: 40,
                  height: 200,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: item['segments'].map<Widget>((seg) {
                      double heightPercentage = seg['value'] / 100;
                      return Container(
                        width: double.infinity,
                        height: 200 * heightPercentage,
                        color: seg['color'],
                        child: Center(
                          child: Text(
                            '${seg["value"]}%',
                            style: const TextStyle(color: Colors.white, fontSize: 10),
                          ),
                        ),
                      );
                    }).toList(),
                  ),
                ),
                const SizedBox(height: 8),
                Text(item['label'], style: const TextStyle(fontSize: 12)),
              ],
            );
          }).toList(),
        ),
      ],
    );
  }

  Widget _buildLegendItem(Color color, String label) {
    return Row(
      children: [
        Container(width: 12, height: 12, color: color),
        const SizedBox(width: 4),
        Text(label, style: const TextStyle(fontSize: 12)),
      ],
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:01:34