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
相关产品推荐
相关产品推荐

