1. 基本介绍
Stepper 是 flutter 提供的步骤选择器。
2. 示例代码
代码下载地址。如果对你有帮助的话记得给个关注,代码会根据我的 Flutter 专题不断更新。
3. 属性介绍
Stepper 属性 | 介绍 |
---|---|
steps | @required |
physics | 滑动的物理效果 |
type | Stepper 类型,分为横向与纵向两种,默认为 StepperType.vertical |
currentStep | 当前 step,默认为 0 |
onStepTapped | step 点击回调函数 |
onStepContinue | Next 按钮点击回调函数 |
onStepCancel | Cancel 按钮点击回调函数 |
controlsBuilder | 内容下方按钮构建函数 |
Step 属性 | 介绍 |
---|---|
title | @required 标题控件 |
subtitle | 副标题控件 |
content | @required 内容控件 |
state | 当前 step 的状态,StepState 会改变每一个 step 的图标,默认为 StepState.indexed |
isActive | 是否激活状态,默认为 false,isActive == true 时会变成蓝色 |
4. Stepper 详解
Stepper 的属性其实比较简单,更多的其实是 Stepper 之外的逻辑,在文章末尾会对整体思路进行归纳。
import 'package:flutter/material.dart';
class FMStepperVC extends StatefulWidget{
@override
FMStepperState createState() => FMStepperState();
}
class FMStepperState extends State {
int _currentStep = 0;
List _datas = [];
@override
void initState(){
super.initState();
initData();
}
void initData(){
_datas.clear();
_datas.add(FMStepperModel("第一步", "我们先进行第一步", 0));
_datas.add(FMStepperModel("第二步", "我们先进行第二步", 1));
_datas.add(FMStepperModel("第三步", "我们先进行第三步", 2));
_datas.add(FMStepperModel("第三步", "我们先进行第四步", 3));
_datas.add(FMStepperModel("第三步", "我们先进行第五步", 4));
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(title: Text("Stepper"),),
body: _listView(),
);
}
ListView _listView(){
return ListView(
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
width: 500,
height: 200,
child: _stepper(StepperType.horizontal),
),
),
Padding(
padding: EdgeInsets.all(15),
child: Container(
color: Colors.yellow,
height: 30,
alignment: Alignment.center,
child: Text("下方为纵向 Stepper"),
),
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
width: 400,
height: 500,
child: _stepper(StepperType.vertical),
),
),
],
);
}
Stepper _stepper(type){
return Stepper(
currentStep: _currentStep, // 当前 step
physics: ClampingScrollPhysics(), // 滑动的物理效果
type: type, // Stepper 类型,分为横向与纵向两种, StepperType
// 内容下方按钮构建函数
controlsBuilder: (BuildContext context, {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
children: [
FlatButton(
onPressed: onStepContinue,
child: const Text('NEXT'),
),
FlatButton(
onPressed: onStepCancel,
child: const Text('CANCEL'),
),
FlatButton(
onPressed: (){
print("自定义按钮点击事件");
},
child: const Text('自定义按钮'),
)
],
);
},
// step 点击回调函数
onStepTapped: (index){
print(index);
_currentStep = index;
setState(() {
});
},
// Cancel 按钮点击回调函数
onStepCancel: (){
if(_currentStep > 0){
_currentStep--;
}
setState(() {
});
},
// Next 按钮点击回调函数
onStepContinue: (){
if(_currentStep < _datas.length - 1){
_currentStep++;
}
setState(() {
});
},
// 子控件数组
steps: _steps(),
);
}
// 创建 steps 数组
List _steps(){
List steps = [];
_datas.forEach((model) {
// 我们根据当前 step 进行区分,当前 step 之前的认为 StepState.complete,当前认为 StepState.editing,之后认为 StepState.indexed
if(_currentStep < model.index) {
model.state = StepState.indexed;
} else if(_currentStep == model.index) {
model.state = StepState.editing;
} else if(_currentStep > model.index){
model.state = StepState.complete;
}
steps.add(
Step(
// 标题控件
title: Row(
children: [
Icon(Icons.title),
Text("title"),
],
),
subtitle: Text("subTitle"), // 副标题控件
content: Text("${model.content}"), // 内容控件
isActive: (_currentStep == _datas.indexOf(model)), // 是否激活状态,true 时会变成蓝色
state: model.state, // 当前 step 的状态,StepState 会改变每一个 step 的图标
),
);
});
return steps;
}
}
class FMStepperModel {
String title;
String content;
int index;
StepState state = StepState.indexed;
FMStepperModel(this.title, this.content, this.index);
}
5. 技术小结
- 第一步,我们既然要做一个 Stepper,我们要准备一套数据模型,并且模型包含了状态,标题,内容,下标,等各个元素,然后将这些数据构造出来当做数据源。
- 第二步,我们创建 Stepper,并对一些属性进行设置。
- 第三步,我们创建 steps,这里很重要,要根据我们第一步中的数据源,将每一个 model 构造成对应的 Step 控件。
- 第四步,我们在创建 steps 时,对 model 的状态进行管理,设置编辑中,已完成,未完成等不同状态。
- 第五步,我们对 Stepper 的交互事件进行处理,点击时将 currentStep 设置到对应 index,cancel 时我们执行 currentStep -1 操作,Next 时我们执行 currentStep +1 操作,此处注意防止越界。