【问题标题】:Sliding form steps in Flutter?Flutter中的滑动表单步骤?
【发布时间】:2023-03-16 17:12:01
【问题描述】:

我正在 Flutter 中创建一个注册表单,我希望用户完成这些步骤。每一步都应该以滑动的效果过渡到下一步。例如,如果我在第 1 步,移动到第 2 步应该将表单向左滑动,我应该得到表单 2。然后如果我回到表单 1,它应该将表单向右滑动。

这是一个插图:

我尝试使用多条路线来做到这一点:

routes: {
    '/': (context) => HomePage(),
    '/step1': (context) => FormStep1(),
    '/step2': (context) => FormStep2(),
},

然后提交:

Navigator.push(
    context,
    EnterExitRoute(exitPage: FormStep1(), enterPage: FormStep2())
);

EnterExitRoute

但这也会使 App Bar 滑动,我只希望表单滑动。

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    在朋友的建议下,我最终使用了PageView。这样我就不必为每一步都创建新的路线。

    class _RegisterFormState extends State<RegisterForm> {
      final _formsPageViewController = PageController();
      List _forms;
    
    
      @override
      Widget build(BuildContext context) {
        _forms = [
          WillPopScope(
            onWillPop: () => Future.sync(this.onWillPop),
            child: Step1Container(),
          ),
          WillPopScope(
            onWillPop: () => Future.sync(this.onWillPop),
            child: Step2Container(),
          ),
        ];
    
        return Expanded(
          child: PageView.builder(
            controller: _formsPageViewController,
            physics: NeverScrollableScrollPhysics(),
            itemBuilder: (BuildContext context, int index) {
              return _forms[index];
            },
          ),
        );
      }
    
      void _nextFormStep() {
        _formsPageViewController.nextPage(
          duration: Duration(milliseconds: 300),
          curve: Curves.ease,
        );
      }
    
      bool onWillPop() {
        if (_formsPageViewController.page.round() ==
            _formsPageViewController.initialPage) return true;
    
        _formsPageViewController.previousPage(
          duration: Duration(milliseconds: 300),
          curve: Curves.ease,
        );
    
        return false;
      }
    }
    

    说明:

    • 我用WillPopScope 包装每个表单,所以“返回”按钮将 影响导航。
    • 我在PageView 构建器上使用physics: NeverScrollableScrollPhysics() 选项,因此它不会受到滑动手势的影响。
    • 在表单步骤的每个按钮上(最后一步除外)我调用_nextFormStep() 方法,移至下一个表单。
    • 列表中每个WillPopScope() 的子级只是您想要滑动的表单/小部件。

    【讨论】:

    • 我需要这个确切的东西,但我迷路了,没有实现 this.onWillPop 也没有调用 _submit 方法。
    • @mwieczorek 我添加了onWillPop() 方法。单击“下一步”按钮时只需调用_submit。它可以有一个更好的名字,比如_nextFormStep()
    【解决方案2】:

    作为一个选项,您可以使用 Navigator 小部件包装页面 像这样的

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(title: Text('Title')),
            body: SafeArea(
              child: WillPopScope(
                onWillPop: () async => !await _navigatorKey.currentState.maybePop(),
                child: Navigator(
                  key: _navigatorKey,
                  onGenerateRoute: (settings) {
                    switch (settings.name) {
                      case '/':
                        return MaterialPageRoute(builder: (context) => HomePage());
                        break;
                      case '/step1':
                        return CupertinoPageRoute(builder: (context) => FormStep1());
                        break;
                      case '/step2':
                        return CupertinoPageRoute(builder: (context) => FormStep2());
                        break;
                    }
                  },
                ),
              ),
            ),
          ),
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.green[200],
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('HomePage'),
              RaisedButton(
                onPressed: () => Navigator.pushNamed(context, '/step1'),
                child: Text('Start'),
              ),
            ],
          ),
        );
      }
    }
    
    class FormStep1 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.blue[200],
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('FormStep1'),
              RaisedButton(
                onPressed: () => Navigator.pushNamed(context, '/step2'),
                child: Text('Next'),
              ),
            ],
          ),
        );
      }
    }
    
    class FormStep2 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.yellow[200],
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('FormStep2'),
              RaisedButton(onPressed: () {}, child: Text('Next')),
            ],
          ),
        );
      }
    }
    

    除了 CupertinoPageRoute,您还可以使用任何自定义 Route 进行任何转换

    【讨论】:

    • 这里无法使用TextFormField之类的输入,无法打开键盘
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    相关资源
    最近更新 更多