前言
我们在应用里,会经常遇到一项业务有多个步骤,比如订单状态,任务进展等等,这个时候就需要用到步骤指示器,也叫步骤条。步骤条可以让用户清晰地知道整个业务会经历哪些环节,以及当前所处的状态,如下图所示。
这种步骤条自己实现还挺麻烦的,不过已经有人给我们造好“轮子”了,这就是我们本篇要介绍的easy_stepper。
easy_stepper 简介
easy_stepper
专门用于指示步骤,其优点是简单易用,而且可以高度自定义。因此,我们可以基于它实现各种花里胡哨(不实用)的步骤条,比如下面这种效果。
我们先来看最基础的使用,也就是我们在前言中贴的截图:
SingleChildScrollView(
child: EasyStepper(
direction: Axis.horizontal,
disableScroll: false,
alignment: Alignment.center,
activeStep: activeStep,
lineLength: 50,
lineSpace: 0,
lineType: LineType.normal,
defaultLineColor: toBeFinishedColor,
finishedLineColor: finishedColor,
activeStepTextColor: activeColor,
finishedStepTextColor: finishedColor,
internalPadding: 0,
padding: const EdgeInsetsDirectional.symmetric(
horizontal: 10, vertical: 40),
showLoadingAnimation: false,
stepRadius: 8.0,
showStepBorder: false,
lineThickness: 1.0,
steps: [
EasyStep(
customStep: CircleAvatar(
backgroundColor: _getStepColor(0),
),
title: '待付款',
),
EasyStep(
customStep: CircleAvatar(
backgroundColor: _getStepColor(1),
),
title: '已付款',
topTitle: true,
),
EasyStep(
customStep: CircleAvatar(
backgroundColor: _getStepColor(2),
),
title: '运输中',
),
EasyStep(
customStep: CircleAvatar(
backgroundColor: _getStepColor(3),
),
title: '已收货',
topTitle: true,
),
EasyStep(
customStep: CircleAvatar(
backgroundColor: _getStepColor(4),
),
title: '交易完成',
),
EasyStep(
customStep: CircleAvatar(
backgroundColor: _getStepColor(5),
),
title: '已评价',
topTitle: true,
),
],
onStepReached: (index) => setState(() => activeStep = index),
),
)
按照示例写一个 EasyStepper
,注意需要包裹在 SingleChildScrollView
里(如果不包裹样式会有问题)。其中前面那部分参数都是配置步骤条的展示方式,具体参数说明如下:
direction
:横向还是纵向,默认横向,如果节点比较多,推荐使用纵向,比如任务节点或者 OA 审批流转节点。disableScroll
:是否禁止滚动,当步骤条的内容超出宽度或高度时,默认是支持滚动的,也可以禁止滚动。alignment
:步骤条各个节点的对齐方式。activeStep
:当前活跃的步骤节点。lineLength
:线段长度。xxColor
:线条或步骤条节点文字的颜色,可以配置不同状态节点的边框、文本和线条的颜色。showLoadingAnimation
:是否显示Loading
动效等等。stepRadius
:步骤节点的半径大小,也可以不指定,通过自定义组件实现自定义大小。lineThickness
:步骤线段粗细。steppingEnabled
:是否启用步骤节点(不启用则点击无效果),也可以在EasyStep
里禁用单个节点。enableStepTapping
:步骤节点是否允许Tap,如果允许会有按压效果指示。steps
:一个EasyStep
数组,可以在里面定义各个节点的组件及属性,比如标题是不是放上面(topTitle
),节点使用什么组件。这里就可以自定义自己的节点样式。onStepReached
:步骤交互响应,当步骤发生变更时会调用该方法,告诉我们当前进行到了哪个步骤了。我们可以利用这个回调来更改界面或完成相应的业务逻辑。lineType
:正常(normal)是实线,可以绘制虚线,此时参数值为LineType.dotted
。lineSpace
:当使用虚线时(lineType
为LineType.dotted
),可以指定虚线点之间的间距,如果是0那么还是会是实线。padding
:节点与父组件之间的内边距,可以通过这个来调节步骤条与父组件的距离。internalPadding
:节点之间的间距。reachedSteps
:当前已经达到节点(但未完成,比如节点负责人已读消息)下标集合,当节点下标在这个集合里面时,边框和标题会变颜色为完成状态颜色,但是节点自身不会。例如下面的蓝色外边框,内部是灰色圆的就是这种节点。
实际还有不少参数,大家可以看源码了解具体参数的用途。下面我们来看几个典型的示例。
使用图标作为节点
这个在电商领域比较常见,用图标代替圆点会更加简洁形象。
实现的源码是通过一个 Row
组件,然后使用 Flex
布局,将上一步、下一步的按钮和步骤条放在一起。这里需要注意,如果是 Row
组件,那么步骤条需要使用Expanded
包裹住。源码如下:
child: SingleChildScrollView(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(flex: 1, child: _previousStep(StepEnabling.individual)),
Expanded(
flex: 15,
child: EasyStepper(
activeStep: activeStep2,
reachedSteps: reachedSteps,
lineLength: 100,
lineSpace: 4,
lineType: LineType.dotted,
activeStepBorderColor: Colors.blue,
activeStepIconColor: Colors.blue,
activeStepTextColor: Colors.blue,
activeLineColor: Colors.blueGrey.withOpacity(0.5),
activeStepBackgroundColor: Colors.white,
unreachedStepBackgroundColor:
Colors.blueGrey.withOpacity(0.5),
unreachedStepBorderColor: Colors.blueGrey.withOpacity(0.5),
unreachedStepIconColor: Colors.blueGrey,
unreachedStepTextColor: Colors.blueGrey.withOpacity(0.5),
unreachedLineColor: Colors.blueGrey.withOpacity(0.5),
finishedStepBackgroundColor: Colors.pink.withOpacity(0.5),
finishedStepBorderColor: Colors.blueGrey.withOpacity(0.5),
finishedStepIconColor: Colors.blueGrey,
finishedStepTextColor: Colors.pink.withOpacity(0.5),
finishedLineColor: Colors.pink.withOpacity(0.5),
borderThickness: 2,
internalPadding: 15,
showStepBorder: true,
showLoadingAnimation: false,
stepRadius: 20,
// stepShape: baseStep.StepShape.rRectangle,
showTitle: true,
steps: [
EasyStep(
icon: const Icon(CupertinoIcons.cart),
title: '购物车',
lineText: '添加收货地址',
enabled: _allowTabStepping(0, StepEnabling.individual),
),
EasyStep(
icon: const Icon(CupertinoIcons.info),
title: '填写地址',
lineText: '付款结算',
enabled: _allowTabStepping(1, StepEnabling.individual),
),
EasyStep(
icon: const Icon(CupertinoIcons.cart_fill_badge_plus),
title: '结算',
lineText: '选择付款方式',
enabled: _allowTabStepping(2, StepEnabling.individual),
),
EasyStep(
icon: const Icon(CupertinoIcons.money_dollar),
title: '付款',
lineText: '核对订单',
enabled: _allowTabStepping(3, StepEnabling.individual),
),
EasyStep(
icon: const Icon(Icons.file_present_rounded),
title: '确认订单',
lineText: '提交订单',
enabled: _allowTabStepping(4, StepEnabling.individual),
),
EasyStep(
icon: const Icon(Icons.check_circle_outline),
title: '完成',
enabled: _allowTabStepping(5, StepEnabling.individual),
),
],
onStepReached: (index) => setState(() {
activeStep2 = index;
}),
),
),
Expanded(flex: 1, child: _nextStep(StepEnabling.individual)),
],
),
),
这里我们也可以看到,步骤节点(EasyStep
)之间的线条也是可以加文字说明的,包括标题可以放置在下方,也可以设置放置在节点上方(topTitle
属性为 true
)。
自定义动画
我们有时候会使用动画来标识活跃的节点,在 EasySteper
里,默认是内置了一个 loading
动画,当showLoadingAnimation
为 true
时,就会使用动画展示活跃的节点。如下图所示。
而实际上,是可以使用 Lottie
的 json
动画文件来自定义动画的,比如我自己随便下了一个 Lottie 动画替换了默认的动画。
这个时候,我们只需要配置 EasyStepper
的两个参数就行了,除了showLoadingAnimation
设置为 true
之外,再把下载的 Lottie动画文件路径给loadingAnimation
即可。
child: EasyStepper(
//...
showLoadingAnimation: true,
loadingAnimation: 'images/animation.json',
//...
)
结语
easy_stepper
官方还给了不少其他示例,有兴趣的可以自行去看一下。个人感受来说,这个组件是可以拿来就用的,相比自己开发的话,会更加高效。本篇的源码已经提交至Flutter 实用组件相关源码。
我是岛上码农,微信公众号同名。如有问题可以加本人微信交流,微信号:
island-coder
。👍🏻:觉得有收获请点个赞鼓励一下!
🌟:收藏文章,方便回看哦!
💬:评论交流,互相进步!