Flutter步进器插件cool_stepper_reloaded的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter步进器插件cool_stepper_reloaded的使用

Cool Stepper Reloaded

Pub Version

Cool Stepper Reloaded 是一个显示操作步骤序列的Flutter小部件。它对于表单向导或引导页非常有用。

这个项目是从 Cool Stepper 分支出来的,因为需要一个空安全(null-safety)包,并保持该优秀小部件的活跃开发。感谢emrade和所有帮助构建此小部件的开发者。

屏幕截图

Header启用并带有默认按钮

Header enabled and with default button Header enabled and with default button

Header禁用并带有自定义按钮 Ripple Button

Header disabled and with custom button Header disabled and with custom button

示例代码

下面是一个完整的示例代码,展示了如何使用 cool_stepper_reloaded 插件创建一个多步骤表单。

import 'package:cool_stepper_reloaded/cool_stepper_reloaded.dart';
import 'package:flutter/material.dart';
import 'package:another_flushbar/flushbar.dart';
import 'package:ripple_button/ripple_button.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cool Stepper',
      theme: ThemeData(
        primarySwatch: Colors.pink,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      debugShowCheckedModeBanner: false,
      home: MyHomePage(title: 'Cool Stepper'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);

  final String? title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();
  String? selectedRole = 'Writer';
  final TextEditingController _nameCtrl = TextEditingController();
  final TextEditingController _emailCtrl = TextEditingController();

  @override
  Widget build(BuildContext context) {
    final steps = [
      CoolStep(
        title: 'Basic Information',
        subtitle: 'Please fill some of the basic information to get started',
        alignment: Alignment.center,
        content: Form(
          key: _formKey,
          child: Column(
            children: [
              _buildTextField(
                labelText: 'Name',
                validator: (value) {
                  if (value!.isEmpty) {
                    return 'Name is required';
                  }
                  return null;
                },
                controller: _nameCtrl,
              ),
              _buildTextField(
                labelText: 'Email Address',
                validator: (value) {
                  if (value!.isEmpty) {
                    return 'Email address is required';
                  }
                  return null;
                },
                controller: _emailCtrl,
              ),
            ],
          ),
        ),
        validation: () {
          if (!_formKey.currentState!.validate()) {
            return 'Fill form correctly';
          }
          return null;
        },
      ),
      CoolStep(
        title: 'Select your role',
        subtitle: 'Choose a role that better defines you',
        alignment: Alignment.center,
        content: Container(
          child: Row(
            children: <Widget>[
              _buildSelector(
                context: context,
                name: 'Writer',
              ),
              SizedBox(width: 5.0),
              _buildSelector(
                context: context,
                name: 'Editor',
              ),
            ],
          ),
        ),
      ),
    ];

    void _onFinish() {
      final flush = Flushbar(
        message: 'Steps completed!',
        flushbarStyle: FlushbarStyle.FLOATING,
        margin: EdgeInsets.all(8.0),
        borderRadius: BorderRadius.all(Radius.circular(8.0)),
        icon: Icon(
          Icons.check_circle_outline_outlined,
          size: 28.0,
          color: Colors.green,
        ),
        duration: Duration(seconds: 2),
        leftBarIndicatorColor: Colors.green,
      );
      flush.show(context);
    }

    final stepper = CoolStepper(
      showErrorSnackbar: true,
      hasRoundedCorner: true,
      onCompleted: _onFinish,
      contentPadding: EdgeInsets.only(left: 40, right: 40),
      config: CoolStepperConfig(
        finishButton: Container(
          child: RippleButton(
            text: 'Finish',
            type: RippleButtonType.AMBER,
            padding: EdgeInsets.only(right: 16, bottom: 6),
            style: RippleButtonStyle(
              width: 20,
            ),
            onPressed: () => {},
          ),
        ),
        backButton: RippleButton(
          text: 'Back',
          type: RippleButtonType.BLUE_TRANSLUCENT,
          padding: EdgeInsets.only(left: 16, bottom: 6),
          style: RippleButtonStyle(
            width: 24,
          ),
          onPressed: () => {},
        ),
        nextButton: RippleButton(
          text: 'Next',
          type: RippleButtonType.AMBER,
          padding: EdgeInsets.only(right: 16, bottom: 6),
          style: RippleButtonStyle(
            width: 20,
          ),
          onPressed: () => {},
        ),
      ),
      steps: steps,
    );

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: Container(
        child: stepper,
      ),
    );
  }

  Widget _buildTextField({
    String? labelText,
    FormFieldValidator<String>? validator,
    TextEditingController? controller,
  }) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 20.0),
      child: TextFormField(
        decoration: InputDecoration(
          labelText: labelText,
        ),
        validator: validator,
        controller: controller,
      ),
    );
  }

  Widget _buildSelector({
    BuildContext? context,
    required String name,
  }) {
    final isActive = name == selectedRole;

    return Expanded(
      child: AnimatedContainer(
        duration: Duration(milliseconds: 200),
        curve: Curves.easeInOut,
        decoration: BoxDecoration(
          color: isActive ? Theme.of(context!).primaryColor : null,
          border: Border.all(
            width: 0,
          ),
          borderRadius: BorderRadius.circular(8.0),
        ),
        child: RadioListTile(
          value: name,
          activeColor: Colors.white,
          groupValue: selectedRole,
          onChanged: (String? v) {
            setState(() {
              selectedRole = v;
            });
          },
          title: Text(
            name,
            style: TextStyle(
              color: isActive ? Colors.white : null,
            ),
          ),
        ),
      ),
    );
  }
}

CoolStepper 类属性

属性名 数据类型 描述 默认值
onCompleted Void Function() 必填 - 所有步骤完成后触发的函数 Null
steps List<CoolStep> 必填 - 步骤列表 Null
config CoolStepperConfig 用于自定义步进器 CoolStepperConfig(backText: “BACK”, nextText: “NEXT”, stepText: “STEP”, ofText: “OF”)
alignment Alignment 更改内容对齐方式,介于标题(如果启用)和按钮之间 Alignment.topCenter
isHeaderEnabled bool 是否为每个步骤构建标题,默认值为true true
showErrorSnackbar bool 如果验证失败,是否显示包含错误信息的SnackBar false

CoolStepperConfig 属性

属性名 数据类型 描述 默认值
backText String 返回按钮上显示的文本 BACK
nextText String 下一步按钮上显示的文本 NEXT
finalText String 最后一步的下一步按钮上显示的文本 FINISH
stepText String 描述进度的文本 STEP
ofText String 描述进度的文本 OF
headerColor Color 标题的背景颜色 Theme.of(context).primaryColor.withOpacity(0.1)
icon Icon 替换默认图标的图标 Icon(Icons.help_outline, size: 18, color: Colors.black38)
titleTextStyle TextStyle 标题文本样式 TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, color: Colors.black38)
subtitleTextStyle TextStyle 副标题文本样式 TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600, color: Colors.black)
backTextList List<String> 覆盖’backText’的字符串列表,必须比步骤数少一个,因为第一步不会显示返回按钮 null
nextTextList List<String> 覆盖’nextText’的字符串列表,必须比步骤数少一个,因为可以通过’finalText’设置最后一步的下一步按钮文本 null

待办事项

  • ✅ 添加自定义“下一步”按钮的文本样式参数 (2.2.0)
  • ✅ 添加自定义“返回”按钮的文本样式参数 (2.2.0)
  • ❌ 添加自定义“步骤 x of N”的文本样式参数
  • ❌ 添加更改“下一步”按钮背景颜色的选项
  • ❌ 添加更改“完成”按钮背景颜色的选项

请在遇到问题或文档不清晰时提交问题。

许可证

参见 LICENSE.md


更多关于Flutter步进器插件cool_stepper_reloaded的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter步进器插件cool_stepper_reloaded的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用cool_stepper_reloaded插件的示例代码。这个插件允许你创建一个步进器(Stepper),用于引导用户完成一系列步骤。

首先,确保你已经在pubspec.yaml文件中添加了cool_stepper_reloaded依赖:

dependencies:
  flutter:
    sdk: flutter
  cool_stepper_reloaded: ^最新版本号  # 请替换为实际发布的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Dart文件中,你可以这样使用cool_stepper_reloaded

import 'package:flutter/material.dart';
import 'package:cool_stepper_reloaded/cool_stepper_reloaded.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  final List<Step> steps = [
    Step(
      title: Text('Step 1: Enter Name'),
      content: TextFormField(
        decoration: InputDecoration(labelText: 'Name'),
      ),
    ),
    Step(
      title: Text('Step 2: Enter Age'),
      content: TextFormField(
        decoration: InputDecoration(labelText: 'Age'),
        keyboardType: TextInputType.number,
      ),
    ),
    Step(
      title: Text('Step 3: Submit'),
      content: ElevatedButton(
        onPressed: () {
          // Handle submission here
          print('Step completed');
        },
        child: Text('Submit'),
      ),
    ),
  ];

  int currentStep = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Cool Stepper Reloaded Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: CoolStepper(
          steps: steps,
          currentStep: currentStep,
          onStepTapped: (step) {
            setState(() {
              currentStep = step;
            });
          },
          onStepContinue: () {
            if (currentStep < steps.length - 1) {
              setState(() {
                currentStep += 1;
              });
            }
          },
          onStepBack: () {
            if (currentStep > 0) {
              setState(() {
                currentStep -= 1;
              });
            }
          },
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们定义了一个包含三个步骤的列表steps。每个步骤包含一个标题和一个内容。对于前两个步骤,内容是一个TextFormField,用于输入名字和年龄。第三个步骤是一个按钮,用于提交信息。

  2. 我们创建了一个CoolStepper组件,并将步骤列表、当前步骤、以及用于处理步骤点击、继续和返回的回调函数传递给它。

  3. 使用setState方法来更新当前步骤,这样步进器就会显示正确的步骤。

你可以根据需要修改步骤的内容和逻辑,以适应你的具体需求。这个示例提供了一个基本的框架,展示了如何使用cool_stepper_reloaded插件来创建步进器。

回到顶部