Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sliding form steps in Flutter?

Tags:

flutter

dart

I'm creating a registration form in Flutter, and I would like the user to go through steps. Every step should transition to the next step with a sliding effect. For example, if I am on Step 1, moving to Step 2 should slide the form to the left, and I should get Form 2. Then if I go back to form 1, it should slide the form to the right.

Here's an illustration: enter image description here

I tried to do that with multiple routes:

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

Then on submit:

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

EnterExitRoute

But that makes the App Bar slide as well, and I want only the form to slide.

like image 968
HTMHell Avatar asked Jun 17 '19 11:06

HTMHell


People also ask

How do you adjust the slider width on a flutter?

You can use SliderTheme to customize the slider appearance and wrap Slider with Container to give custom width for the slider. It will take Container width as Slider width.


1 Answers

With an advice from a friend, I ended up using PageView. That way I didn't have to make a new route for every step.

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;
  }
}

Explanation:

  • I'm wrapping every form with WillPopScope so "back" button will affect navigation.
  • I'm using physics: NeverScrollableScrollPhysics() option on the PageView builder so it will not be affected by a swipe gesture.
  • On each button of a form step (except last step) I call the _nextFormStep() method, which moves to the next form.
  • The child of each WillPopScope() in the list is simply the form / widget you want to be slided.
like image 12
HTMHell Avatar answered Oct 22 '22 07:10

HTMHell