如何将Flutter图表代码重构为搭载Scaffold的StatefulWidget?
Flutter fl_chart 嵌入StatefulWidget+Scaffold实现方案
你现有的LineTitles静态配置类不需要大幅修改,核心是将图表嵌入StatefulWidget的构建逻辑,用Scaffold作为页面根容器即可,以下是可直接运行的完整实现。
1. 现有代码适配说明
你写的LineTitles是纯逻辑工具类,不依赖组件生命周期,仅做了两处小优化:
- 方法名调整为Dart规范的小驼峰格式
getTitleData(原大写开头的命名也可正常运行,不做强制要求) - 新增了顶部、右侧标题的隐藏配置,避免页面显示冗余刻度
2. 完整可运行代码
import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; // 原有标题配置类,可直接复用 class LineTitles { static FlTitlesData getTitleData() => FlTitlesData( show: true, // 隐藏右侧和顶部冗余标题 rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, reservedSize: 35, getTitlesWidget: (value, meta) { switch (value.toInt()) { case 2: return const Text( 'MAR', style: TextStyle( color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 16, ), ); case 5: return const Text( 'JUN', style: TextStyle( color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 16, ), ); case 8: return const Text('SEP', style: TextStyle( color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 16, )); } return const Text(" "); }), ), leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, reservedSize: 35, getTitlesWidget: (value, meta) { switch (value.toInt()) { case 1: return const Text( '10k', style: TextStyle( color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 15, ), ); case 3: return const Text( '30k', style: TextStyle( color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 15, ), ); case 5: return const Text('50k', style: TextStyle( color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 15, )); } return const Text(" "); })), ); } void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData.light(useMaterial3: true), home: const ChartPage(), ); } } // 动态图表页面,使用StatefulWidget实现 class ChartPage extends StatefulWidget { const ChartPage({super.key}); @override State<ChartPage> createState() => _ChartPageState(); } class _ChartPageState extends State<ChartPage> { // 折线数据存在状态类中,后续可动态修改 List<FlSpot> chartSpots = const [ FlSpot(0, 1), FlSpot(2, 2), FlSpot(5, 3), FlSpot(8, 4), FlSpot(10, 5), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('业务数据折线图'), centerTitle: true, ), body: Padding( padding: const EdgeInsets.all(24.0), child: AspectRatio( aspectRatio: 1.5, child: LineChart( LineChartData( titlesData: LineTitles.getTitleData(), minX: 0, maxX: 10, minY: 0, maxY: 6, gridData: const FlGridData(show: true), borderData: FlBorderData(show: true), lineBarsData: [ LineChartBarData( spots: chartSpots, isCurved: true, color: Colors.blue, barWidth: 3, dotData: const FlDotData(show: true), ) ], ), ), ), ), // 示例浮动按钮,演示动态更新数据逻辑 floatingActionButton: FloatingActionButton( onPressed: () { setState(() { // 修改状态即可触发图表重绘 chartSpots = const [ FlSpot(0, 2), FlSpot(2, 3), FlSpot(5, 4), FlSpot(8, 5), FlSpot(10, 3), ]; }); }, child: const Icon(Icons.refresh), ), ); } }
3. 动态更新图表的使用方式
- 所有需要动态修改的图表配置(比如折线点数据、选中状态、时间维度)都定义在State类的成员变量中,和示例里的
chartSpots逻辑一致 - 需要更新图表时,在交互逻辑(按钮点击、接口返回、选择器切换)里调用
setState()修改对应变量,图表会自动重绘生效 - 静态标题配置每次build时都会自动加载,不会因为状态更新出现显示异常
- 可以根据业务需求在Scaffold中扩展其他模块:比如在
appBar下加筛选栏、在图表周围加数据统计卡片、在底部加操作按钮,和普通Widget布局逻辑完全一致
注意事项
- 提前在
pubspec.yaml中添加fl_chart依赖,当前代码适配0.6.x及以上版本,和你现有代码的API完全匹配 - 如果需要调整图表尺寸,在外层嵌套
Container或AspectRatio组件约束宽高即可,避免布局溢出
内容的提问来源于stack exchange,提问作者pomoworko.com
相关产品推荐
相关产品推荐

