Flutter 69: 图解基本 Stepper 步进器

简介: 0 基础学习 Flutter,第六十九步:学习一下基本 Stepper!

      小菜尝试做一个积分进度和类似物流进度的小组件,优先考虑的是自定义 ListView 但还是查阅了一下资料,发现神奇的 Stepper 步进器,虽不能完全满足需求,但提供了很好的思路,小菜仅就基本的 Stepper 学习一下;

源码分析

const Stepper({
    Key key,
    @required this.steps,               // Step 列表
    this.physics,                       // 滑动动画
    this.type = StepperType.vertical,   // 方向:横向/纵向
    this.currentStep = 0,               // 当前所在 Step
    this.onStepTapped,                  // Step 点击回调
    this.onStepContinue,                // Step 继续按钮回调
    this.onStepCancel,                  // Step 取消按钮回调
    this.controlsBuilder,               // 自定义控件
})

class Step 
  const Step({
    @required this.title,           // 标题
    this.subtitle,                  // 副标题
    @required this.content,         // 内容
    this.state = StepState.indexed, // 状态
    this.isActive = false,          // 是否高亮
  })
}

      分析源码可知,Stepper 中存放的是 Step 列表,且 Step 数量不可变,其中包括了点击的回调等;Step 只是一个类而非 Widget 故不能单独使用;

案例尝试

Step

  1. title 为描述性标题;content 为标题与副标题之下的内容,默认包含 continuecancel 按钮;两者均为 Widget 且不可为 null
return Stepper(steps: [
  Step(title: Text('Step 标题一'), content: Container(color: Colors.orangeAccent.withOpacity(0.4), child: Text('Step 内容一'))),
  Step(title: Text('Step 标题二'), content: Container(color: Colors.blueAccent.withOpacity(0.4), child: Text('Step 内容二'))),
  Step(title: Text('Step 标题三'), content: Container(color: Colors.purple.withOpacity(0.4), child: Text('Step 内容三')))
]);

  1. subtitle 为副标题,在 title 之下,默认小一个字号;
return Stepper(steps: [
  Step(title: Text('Step 标题一'), subtitle: Text('Step 副标题一'),
      content: Container(color: Colors.orangeAccent.withOpacity(0.4), child: Text('Step 内容一'))),
  Step(title: Text('Step 标题二'), subtitle: Text('Step 副标题二'),
      content: Container(color: Colors.blueAccent.withOpacity(0.4), child: Text('Step 内容二'))),
  Step(title: Text('Step 标题三'), subtitle: Text('Step 副标题三'),
      content: Container(color: Colors.purple.withOpacity(0.4), child: Text('Step 内容三')))
]);

  1. state 为状态,Flutter 默认提供了多种状态样式;
    a. indexed: 在圆中展示每个 Step 数组下标(从 1 开始);

b. editing: 编辑状态,在圆中展示铅笔图标;
c. complete: 完成状态,在圆中展示刻度图标;
d. disabled: 不可用状态,为灰色;
e. error: 错误状态,在红色三角中展示叹号图标;

return Stepper(steps: [
  Step(title: Text('Step state -> indexed'), state: StepState.indexed, content: Container()),
  Step(title: Text('Step state -> editing'), state: StepState.editing, content: Container()),
  Step(title: Text('Step state -> complete'), state: StepState.complete, content: Container()),
  Step(title: Text('Step state -> disabled'), state: StepState.disabled, content: Container()),
  Step(title: Text('Step state -> error'), state: StepState.error, content: Container())
]);

  1. isActive 为设置当前 Step 是否高亮,仅图标高亮,其中 error 状态默认高亮,disabled 状态图标也可高亮;
return Stepper(steps: [
  Step(isActive: true, title: Text('Step state -> indexed'), state: StepState.indexed, content: Container()),
  Step(isActive: true, title: Text('Step state -> editing'), state: StepState.editing, content: Container()),
  Step(isActive: true, title: Text('Step state -> complete'), state: StepState.complete, content: Container()),
  Step(isActive: true, title: Text('Step state -> disabled'), state: StepState.disabled, content: Container()),
  Step(isActive: true, title: Text('Step state -> error'), state: StepState.error, content: Container())
]);

Stepper

  1. type 包括横向 horizontal 展示与纵向 vertical 展示两类,默认是 vertical
return Stepper(type: StepperType.horizontal,
    steps: [
      Step(title: Text('Step 标题一'), content: Container()),
      Step(title: Text('Step 标题二'), content: Container()),
      Step(title: Text('Step 标题三'), content: Container())
    ]);

  1. currentStep 为当前 Step,注意数组下标从 0 开始;
return Stepper(type: StepperType.horizontal, currentStep: 1,
    steps: [
      Step(title: Text('Step 标题一'), content: Container(child: Text('Step 内容一'))),
      Step(title: Text('Step 标题二'), content: Container(child: Text('Step 内容二'))),
      Step(title: Text('Step 标题三'), content: Container(child: Text('Step 内容三')))
    ]);

  1. onStepTappedStep 点击回调,小菜尝试点击切换 Step 时获取当前 Step 高亮;
var _curStep = 0;
return Stepper(currentStep: _curStep,
    onStepTapped: (step) { setState(() {  _curStep = step; }); },
    steps: [
      Step(title: Text('Step 标题一'), content: Container(child: Text('Step 内容一')), isActive: _curStep >= 0 ? true : false),
      Step(title: Text('Step 标题二'), content: Container(child: Text('Step 内容二')), isActive: _curStep >= 1 ? true : false),
      Step(title: Text('Step 标题三'), content: Container(child: Text('Step 内容三')), isActive: _curStep >= 2 ? true : false)
    ]);

  1. onStepContinueStep 中继续按钮点击回调;* 为 Step 中取消按钮点击回调;小菜尝试对继续和取消点击进行 Step* 切换;
return Stepper(currentStep: _curStep,
    onStepTapped: (step) { setState(() {  _curStep = step; }); },
    onStepContinue: () { setState(() { if (_curStep < 2) { _curStep++; } }); },
    onStepCancel: () { setState(() { if (_curStep > 0) { _curStep--; } }); },
    steps: [
      Step(title: Text('Step 标题一'), content: Container(child: Text('Step 内容一')), isActive: _curStep >= 0 ? true : false),
      Step(title: Text('Step 标题二'), content: Container(child: Text('Step 内容二')), isActive: _curStep >= 1 ? true : false),
      Step(title: Text('Step 标题三'), content: Container(child: Text('Step 内容三')), isActive: _curStep >= 2 ? true : false)
    ]);

  1. controlsBuilder 用来自定义继续和取消按钮,若不需要展示则设置空 Widget 即可;
return Stepper(currentStep: _curStep,
    onStepTapped: (step) { setState(() {  _curStep = step; }); },
    onStepContinue: () { setState(() { if (_curStep < 2) { _curStep++; } }); },
    onStepCancel: () { setState(() { if (_curStep > 0) { _curStep--; } }); },
    controlsBuilder: (BuildContext context, {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
      return Row(children: <Widget>[
        Container( width: 100,
            child: Image.asset(_curStep == 0 ? 'images/icon_hzw01.jpg' : _curStep == 1 ? 'images/icon_hzw02.jpg' : 'images/icon_hzw03.jpg')),
        SizedBox(width: 30, height: 30),
        Column(children: <Widget>[
          FlatButton(color: Colors.orangeAccent.withOpacity(0.4), onPressed: onStepContinue, child: Text('下一步')),
          FlatButton(color: Colors.purple.withOpacity(0.4), onPressed: onStepCancel, child: Text('上一步'))
        ])
      ]);
    },
    steps: [
      Step(title: Text('Step 标题一'), content: Container(child: Text('Step 内容一')), isActive: _curStep >= 0 ? true : false),
      Step(title: Text('Step 标题二'), content: Container(child: Text('Step 内容二')), isActive: _curStep >= 1 ? true : false),
      Step(title: Text('Step 标题三'), content: Container(child: Text('Step 内容三')), isActive: _curStep >= 2 ? true : false)
    ]);

  1. physics 为滑动属性,小菜测试将 Stepper 放在 ListView 中且不能完全展示时,设置 ClampingScrollPhysics() 可连续滑动;
physics: ClampingScrollPhysics(),


      Stepper 使用方便快捷,虽样式相对固定无法满足所有需求,但给我们提供了很好的自定义思路;小菜对 Stepper 研究尚浅,如有错误请多多指导!

来源: 阿策小和尚

目录
相关文章
|
6月前
Flutter 之 Stepper
Flutter 之 Stepper Stepper 组件在移动端应用中经常被使用,它可以让用户通过一系列步骤来完成一个复杂的操作。Flutter 中的 Stepper 组件提供了一个简单的方式来实现这个功能。
Flutter基础widgets教程-Stepper篇
Flutter基础widgets教程-Stepper篇
293 0
|
1月前
|
Android开发 iOS开发 容器
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
|
5月前
|
开发框架 前端开发 测试技术
Flutter开发常见问题解答
Flutter开发常见问题解答
|
28天前
|
开发者
鸿蒙Flutter实战:07-混合开发
鸿蒙Flutter混合开发支持两种模式:1) 基于har包,便于主项目开发者无需关心Flutter细节,但不支持热重载;2) 基于源码依赖,利于代码维护与热重载,需配置Flutter环境。项目结构包括AppScope、flutter_module等目录,适用于不同开发需求。
69 3
|
13天前
|
传感器 开发框架 物联网
鸿蒙next选择 Flutter 开发跨平台应用的原因
鸿蒙(HarmonyOS)是华为推出的一款旨在实现多设备无缝连接的操作系统。为了实现这一目标,鸿蒙选择了 Flutter 作为主要的跨平台应用开发框架。Flutter 的跨平台能力、高性能、丰富的生态支持和与鸿蒙系统的良好兼容性,使其成为理想的选择。通过 Flutter,开发者可以高效地构建和部署多平台应用,推动鸿蒙生态的快速发展。
114 0
|
15天前
|
Dart 安全 UED
Flutter&鸿蒙next中的表单封装:提升开发效率与用户体验
在移动应用开发中,表单是用户与应用交互的重要界面。本文介绍了如何在Flutter中封装表单,以提升开发效率和用户体验。通过代码复用、集中管理和一致性的优势,封装表单组件可以简化开发流程。文章详细讲解了Flutter表单的基础、封装方法和表单验证技巧,帮助开发者构建健壮且用户友好的应用。
55 0
|
1月前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
74 7
|
28天前
|
编解码 Dart API
鸿蒙Flutter实战:06-使用ArkTs开发Flutter鸿蒙插件
本文介绍了如何开发一个 Flutter 鸿蒙插件,实现 Flutter 与鸿蒙的混合开发及双端消息通信。通过定义 `MethodChannel` 实现 Flutter 侧的 token 存取方法,并在鸿蒙侧编写 `EntryAbility` 和 `ForestPlugin`,使用鸿蒙的首选项 API 完成数据的读写操作。文章还提供了注意事项和参考资料,帮助开发者更好地理解和实现这一过程。
56 0
|
28天前
|
Dart Android开发
鸿蒙Flutter实战:03-鸿蒙Flutter开发中集成Webview
本文介绍了在OpenHarmony平台上集成WebView的两种方法:一是使用第三方库`flutter_inappwebview`,通过配置pubspec.lock文件实现;二是编写原生ArkTS代码,自定义PlatformView,涉及创建入口能力、注册视图工厂、处理方法调用及页面构建等步骤。
47 0