0
votes

I am using a PageView.builder to manage a set of 5 pages. The PageView widget allows the user to swipe left/right to navigate between the pages. I can also use a PageController to programatically navigate to different pages, for example at the press of a button. This is all desired behavior. With that said, on the first page I have a form that I would like to validate before allowing the user to continue. With the button, I can just call the form's validation method to check before navigating away, like this:

          onPressed: () {
            if (_formKey.currentState.validate()) {
              //Navigate to next page...
              _pageController.nextPage(duration: Duration(milliseconds: 300), curve: Curves.linear);
            }
          },

My question is: how can I perform this validation before allowing the user to navigate using the swiping gesture?

Thanks

1

1 Answers

0
votes

You can modify the physics of the PageView:

GlobalKey<FormState> _formKey = GlobalKey<FormState>();
StreamController isValidController = StreamController();
bool isValid = false;

List pages;

@override
void initState() {
  super.initState();

  isValidController.stream.listen((value){
    setState(() {
      isValid = value;
    });
  });

  pages = [
    FormPage(isValidController: isValidController, formKey: _formKey,),
    SecondPage(),
    ThirdPage(),
    FourthPage(),
    FifthPage(),
  ];
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: PageView.builder(
      physics: isValid ? ClampingScrollPhysics() : NeverScrollableScrollPhysics(), //changing here
      itemBuilder: (_, index) {
        return pages[index];
      },
    ),
  );
}

@override
void dispose() {
  isValidController.close();
  super.dispose();
}

And in the Page with the Form:

class FormPage extends StatelessWidget {

  final GlobalKey<FormState> formKey;
  final StreamController isValidController;

  const FormPage({Key key, this.formKey, this.isValidController});

  @override
  Widget build(BuildContext context) {
    return Form(
      key: formKey,
      child: Align(
        child: RaisedButton(
          onPressed: () {
            if (formKey.currentState.validate()) {
                isValidController.add(true);
            }
          },
        ),
      ),
    );
  }
}