【问题标题】:Form with multiple steps (wizard style) in Flutter - Best approachFlutter 中的多步骤表单(向导样式) - 最佳方法
【发布时间】:2019-07-24 21:22:51
【问题描述】:

我需要准备一个屏幕来为包含多个字段的表创建新记录。某些字段以先前字段为条件。我最初的尝试包括一个 TabController/TabBarView/Tabs 集,其中每个选项卡都是表单的一部分。

我的两个问题是:

  • 我似乎无法在 TabBarView 中隐藏“选项卡”(图标/文本)本身(我想使用“下一步”按钮)

  • 即使我忍受这种情况,如果我为每个选项卡构建一个小部件,我也需要为每个表单(每个选项卡一个)设置一个 GlobalKey,因为它们无法共享。

是否有另一种方法可以做到这一点,使用另一个小部件或方法,以便将表单分成几个步骤/屏幕,然后将整个数据作为一个整体提交?

【问题讨论】:

    标签: forms flutter dart


    【解决方案1】:

    您可以使用步进器小部件。它可以让您从多个步骤制作垂直或水平向导。

    Stepper({
      Key key,
      @required this.steps,
      this.physics,
      this.type = StepperType.vertical,
      this.currentStep = 0,
      this.onStepTapped,
      this.onStepContinue,
      this.onStepCancel,
      this.controlsBuilder,
    })
    

    您可以按照 Paul Halliday 的示例进行操作 https://developer.school/flutter-how-to-use-the-stepper-widget/

    【讨论】:

    • 这看起来完全像我需要的解决方案。谢谢,我会尽快尝试!
    • @GregoryRay 抱歉,我已经离开 Flutter 一段时间了,对于那个项目,我专门在下面找到了我的解决方案,但你的解决方案对其他问题非常有用,所以是的,绝对接受。谢谢。
    【解决方案2】:

    我想我找到了一种更好的方法来处理这个问题。我将完全丢弃选项卡(尽管我认为可以将这个逻辑“嵌入”到选项卡中),因为 Next/Previous 按钮可能就足够了。我以这种方式保留了一个表单(密钥),并且在保存时它似乎可以完美地工作。

    import 'package:flutter/material.dart';
    
    final _formKey = GlobalKey<FormState>();
    
    void main() => runApp(MyApp());
    
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Sandbox',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: HomePage(),
        );
      }
    }
    
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Sandbox'),
          ),
          body: Container(
             padding: EdgeInsets.all(8.0),
             color: Colors.white,
             child: FormWidget(),
          ),
        );
      }
    }
    
    
    class FormWidget extends StatefulWidget {
    
    
      @override
      _FormWidgetState createState() => _FormWidgetState();
    }
    
    class _FormWidgetState extends State<FormWidget> {
    
    
      int _stepNumber = 1;
    
      final ctl_name = TextEditingController();
      final ctl_age = TextEditingController();
      final ctl_address = TextEditingController();
      final ctl_city = TextEditingController();
    
      void saveData(BuildContext context) {
    
        _formKey.currentState.save();
    
        print(ctl_name.text);
        print(ctl_age.text);
        print(ctl_address.text);
        print(ctl_city.text);
    
      }
    
      void nextPage(BuildContext context) {
    
        setState(() {
          if (_stepNumber == 1)
            _stepNumber = 2;
          else
            _stepNumber = 1;
        });
      }
    
    
      Column formOneBuilder(BuildContext context) {
        return Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Container(
                  padding: const EdgeInsets.all(8.0),
                  decoration: BoxDecoration(border: Border.all(color: Colors.blue)),
                  width: double.infinity,
                  child: Text("STEP 1")
              ),
            ),
            TextFormField(
              controller: ctl_name,
              decoration: const InputDecoration(
                  labelText: 'Step 1 Name'
              ),
            ),
            TextFormField(
              controller: ctl_age,
              decoration: const InputDecoration(
                  labelText: 'Step 2 Age'
              ),
            ),
            Center(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    FlatButton(
                      color: Colors.blue,
                      child: Text('Next'),
                      onPressed: () {nextPage(context);} ,
                    ),
                    Padding(padding: EdgeInsets.only(left: 8)),
                    FlatButton(
                      color: Colors.blue,
                      child: Text('Save'),
                      onPressed: () {saveData(context);} ,
                    ),
                  ],
                ),
              ),
            )
          ],
        );
      }
    
    
      Column formTwoBuilder(BuildContext context) {
    
        return Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Container(
                  padding: const EdgeInsets.all(8.0),
                  decoration: BoxDecoration(border: Border.all(color: Colors.red)),
                  width: double.infinity,
                  child: Text("STEP 2"),
              ),
            ),
            TextFormField(
              controller: ctl_address,
              decoration: const InputDecoration(
                  labelText: 'Step 2 Address'
              ),
            ),
            TextFormField(
              controller: ctl_city,
              decoration: const InputDecoration(
                  labelText: 'Step 2 City'
              ),
            ),
            Center(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    FlatButton(
                      color: Colors.blue,
                      child: Text('Previous'),
                      onPressed: () {nextPage(context);} ,
                    ),
                    Padding(padding: EdgeInsets.only(left: 8)),
                    FlatButton(
                      color: Colors.blue,
                      child: Text('Save'),
                      onPressed: () {saveData(context);} ,
                    ),
                  ],
                ),
              ),
            )
          ],
        );
    
      }
    
      @override
      Widget build(BuildContext context) {
    
        switch (_stepNumber) {
          case 1:
              return Form(
                  key: _formKey,
                  child:
                    this.formOneBuilder(context),
              );
              break;
    
          case 2:
            return Form(
                  key: _formKey,
                  child:
                    this.formTwoBuilder(context),
            );
            break;
        }
    
      }
    
      void dispose() {
    
        ctl_address.dispose();
        ctl_age.dispose();
        ctl_city.dispose();
        ctl_name.dispose();
    
        super.dispose();
    
      }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多