Flutter动态进度条开发:实现带可点击图标的周进度样式
Flutter 实现可交互周进度条组件
1. 定义数据模型
先创建对应后端返回数据的模型类,方便数据解析和使用:
class WeekProgress { final int weekNumber; final double progress; // 0-1之间的数值,代表进度百分比 final IconData icon; final bool isClickable; WeekProgress({ required this.weekNumber, required this.progress, required this.icon, required this.isClickable, }); // 从后端JSON转模型的方法 factory WeekProgress.fromJson(Map<String, dynamic> json) { return WeekProgress( weekNumber: json['weekNumber'], progress: json['progress'].toDouble(), icon: IconData(json['iconCode'], fontFamily: 'MaterialIcons'), isClickable: json['isClickable'], ); } }
2. 构建可交互进度条组件
核心组件包含每个周的进度块,图标支持点击:
class WeeklyProgressBar extends StatelessWidget { final List<WeekProgress> weeklyData; final Function(int weekNumber) onIconTap; const WeeklyProgressBar({ super.key, required this.weeklyData, required this.onIconTap, }); @override Widget build(BuildContext context) { return SizedBox( height: 80, child: ListView.separated( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: weeklyData.length, separatorBuilder: (context, index) => const SizedBox(width: 12), itemBuilder: (context, index) { final week = weeklyData[index]; return _WeekProgressItem( week: week, onTap: week.isClickable ? () => onIconTap(week.weekNumber) : null, ); }, ), ); } } class _WeekProgressItem extends StatelessWidget { final WeekProgress week; final VoidCallback? onTap; const _WeekProgressItem({ required this.week, this.onTap, }); @override Widget build(BuildContext context) { return Column( children: [ // 可点击图标 GestureDetector( onTap: onTap, child: Icon( week.icon, size: 32, color: onTap != null ? Colors.blue : Colors.grey, ), ), const SizedBox(height: 8), // 进度条容器 SizedBox( width: 40, child: Column( children: [ Text('Week ${week.weekNumber}'), const SizedBox(height: 4), LinearProgressIndicator( value: week.progress, minHeight: 6, borderRadius: BorderRadius.circular(3), ), ], ), ), ], ); } }
3. 集成后端数据与使用组件
通过FutureBuilder获取后端数据并渲染组件:
class ProgressScreen extends StatefulWidget { const ProgressScreen({super.key}); @override State<ProgressScreen> createState() => _ProgressScreenState(); } class _ProgressScreenState extends State<ProgressScreen> { Future<List<WeekProgress>> _fetchWeeklyData() async { // 替换为你的后端API请求逻辑 final response = await http.get(Uri.parse('your-backend-api-url')); if (response.statusCode == 200) { List<dynamic> data = jsonDecode(response.body); return data.map((item) => WeekProgress.fromJson(item)).toList(); } else { throw Exception('Failed to load weekly data'); } } void _handleIconTap(int weekNumber) { // 处理图标点击逻辑,比如跳转详情页、弹出提示等 ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Week $weekNumber icon tapped')), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Weekly Progress')), body: FutureBuilder<List<WeekProgress>>( future: _fetchWeeklyData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text('No data available')); } else { return Column( children: [ WeeklyProgressBar( weeklyData: snapshot.data!, onIconTap: _handleIconTap, ), // 其他页面内容 ], ); } }, ), ); } }
关键说明
- 图标交互:通过
GestureDetector控制点击事件,只有isClickable为true时才响应点击,同时用颜色区分可点击状态。 - 进度条适配:使用
LinearProgressIndicator实现基础进度条,可根据需求自定义样式(比如颜色、高度)。 - 后端集成:
_fetchWeeklyData方法需替换成实际的API请求,确保返回数据能正确解析为WeekProgress模型。
内容的提问来源于stack exchange,提问作者Ardeshir ojan
相关产品推荐
相关产品推荐

