Flutter入门(44):Flutter 组件之 Stepper 详解

1. 基本介绍

Stepper 是 flutter 提供的步骤选择器。

Stepper.png

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);
}
Stepper.gif

5. 技术小结

  • 第一步,我们既然要做一个 Stepper,我们要准备一套数据模型,并且模型包含了状态,标题,内容,下标,等各个元素,然后将这些数据构造出来当做数据源。
  • 第二步,我们创建 Stepper,并对一些属性进行设置。
  • 第三步,我们创建 steps,这里很重要,要根据我们第一步中的数据源,将每一个 model 构造成对应的 Step 控件。
  • 第四步,我们在创建 steps 时,对 model 的状态进行管理,设置编辑中,已完成,未完成等不同状态。
  • 第五步,我们对 Stepper 的交互事件进行处理,点击时将 currentStep 设置到对应 index,cancel 时我们执行 currentStep -1 操作,Next 时我们执行 currentStep +1 操作,此处注意防止越界。

你可能感兴趣的:(Flutter入门(44):Flutter 组件之 Stepper 详解)