如何在Flutter中实现截图所示的自定义Stepper?求代码及解析
Flutter 自定义横向步进器UI实现
一、开发清晰指引
- 拆解UI结构:该步进器为横向排列的多步骤指示器,每个步骤包含「圆形状态指示器」「步骤标题」「状态标签」,步骤间通过动态样式的连接线关联
- 组件拆分策略:封装独立的
StepItem逻辑负责单个步骤的渲染,父组件统一管理全局步骤状态与布局 - 状态控制逻辑:通过当前步骤索引,为每个步骤分配「已完成」「当前进行中」「未开始」三种状态,对应不同的样式表现
- 适配处理:使用
Expanded让每个步骤均分宽度,确保在不同屏幕尺寸下的布局一致性
二、完整自定义实现代码
import 'package:flutter/material.dart'; void main() => runApp(const StepperDemoApp()); class StepperDemoApp extends StatelessWidget { const StepperDemoApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('自定义步进器示例')), body: const Padding( padding: EdgeInsets.all(20.0), child: CustomHorizontalStepper( currentStep: 1, steps: [ StepData(title: '订单确认', status: '已完成'), StepData(title: '支付成功', status: '处理中'), StepData(title: '发货准备', status: '未开始'), StepData(title: '已送达', status: '未开始'), ], ), ), ), ); } } // 步骤数据模型 class StepData { final String title; final String status; StepData({required this.title, required this.status}); } class CustomHorizontalStepper extends StatefulWidget { final int currentStep; final List<StepData> steps; const CustomHorizontalStepper({ super.key, required this.currentStep, required this.steps, }); @override State<CustomHorizontalStepper> createState() => _CustomHorizontalStepperState(); } class _CustomHorizontalStepperState extends State<CustomHorizontalStepper> { @override Widget build(BuildContext context) { return Row( children: List.generate(widget.steps.length, (index) { final isCompleted = index < widget.currentStep; final isCurrent = index == widget.currentStep; final isUnStarted = index > widget.currentStep; return Expanded( child: Column( children: [ // 步骤指示器与连接线 Row( children: [ // 圆形状态指示器 Container( width: 32, height: 32, decoration: BoxDecoration( color: isCompleted ? Colors.green : isCurrent ? Colors.blue : Colors.grey.shade300, borderRadius: BorderRadius.circular(16), ), child: Center( child: isCompleted ? const Icon(Icons.check, color: Colors.white, size: 18) : isCurrent ? const Icon(Icons.circle, color: Colors.white, size: 12) : Text( '${index + 1}', style: TextStyle( color: isUnStarted ? Colors.grey : Colors.white, fontSize: 14, fontWeight: FontWeight.bold, ), ), ), ), // 步骤间连接线(最后一个步骤不显示) if (index != widget.steps.length - 1) Expanded( child: Container( height: 2, color: index < widget.currentStep ? Colors.green : Colors.grey.shade300, ), ), ], ), const SizedBox(height: 8), // 步骤标题 Text( widget.steps[index].title, style: TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: isCompleted || isCurrent ? Colors.black87 : Colors.grey, ), textAlign: TextAlign.center, ), const SizedBox(height: 4), // 状态标签 Text( widget.steps[index].status, style: TextStyle( fontSize: 11, color: isCompleted ? Colors.green : isCurrent ? Colors.blue : Colors.grey, ), textAlign: TextAlign.center, ), ], ), ); }), ); } }
三、详细设计解析
状态样式控制
- 通过
currentStep索引判断每个步骤的状态:index < currentStep为已完成(绿色背景+对勾图标),index == currentStep为当前步骤(蓝色背景+空心圆图标),index > currentStep为未开始(灰色背景+步骤数字) - 连接线颜色随步骤状态动态变化,已完成区间显示绿色,未完成区间显示灰色
- 通过
布局逻辑
- 使用
Row+Expanded实现横向均分布局,每个步骤占据相等宽度,适配不同屏幕尺寸 - 单个步骤采用
Column垂直排列指示器、标题、状态标签,保证视觉层级清晰
- 使用
可扩展性设计
- 封装
StepData数据模型,支持自定义每个步骤的标题与状态文本 - 可通过扩展参数添加点击交互(如点击步骤切换当前索引)、自定义颜色主题等功能
- 封装
视觉细节优化
- 统一设置间距(
SizedBox)保证元素间留白合理 - 状态标签使用对应状态的颜色,强化视觉反馈
- 指示器的尺寸、圆角保持一致,保证UI统一性
- 统一设置间距(
内容的提问来源于stack exchange,提问作者Mathan Tr
相关产品推荐
相关产品推荐

