No N
No N

Reputation: 159

Is there a simple way to make android back button act exactly like app bar back button?

I want the hardware back button act exactly like my app bar back button always. I want it for all my screens. WillPopScope seems not easy to use because my appbar will be always the child of the WillPopScope and therefore I would need to pass data to parent for many different cases.

Edit(more details):

In registration page of my app, if the registration process is on going I am blocking the user interaction with the app by using IgnorePointer but of course this does not work for hardware back button.

Also I designed my appbar back button according to the state of the registration page. So there are at least 3 cases for appbar back button. I want all to apply to the hardware back button too. The problem is I am in a child widget therefore I don't want to call function for each case and update the state of the parent widget. It is not useful and It is very painful to do.

Upvotes: 1

Views: 317

Answers (1)

Rick
Rick

Reputation: 2271

If I understood your problem correctly, I have something that might help you. I've implemented this code on one of my projects. However, I have used Provider and Bloc for state management.

signup_page.dart

@override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: ChangeNotifierProvider<SignupProvider>(
        create: (context) => SignupProvider(),
        child: BlocProvider<SignupBloc>(
          create: (context) => _signupBloc,
          child: BlocListener<SignupBloc, SignupState>(
            listener: (context, state) {
              if (state is SignupCancelled) {
                _closeSignup();
              } else if (state is SignupSuccessful) {
                _closeSignup(delay: 1000);
              } else if (state is SignupInitial) {
                _returnToCredentials();
              } else if (state is SignupProceededToDetails) {
                _proceedToDetails();
              }
            },
            child: Scaffold(
              appBar: AppBar(
                title: const Text("Signup"),
              ),
              body: SafeArea(
                child: PageView(
                  controller: _pageController,
                  physics: const NeverScrollableScrollPhysics(),
                  children: <Widget>[
                    const SignupCredentialsForm(),
                    const SignupDetailsForm(),
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

Future<bool> _onWillPop() async {
    int page = _pageController.page.toInt();

    _signupBloc.add(
      BackButtonPressed(page: page),
    );

    return false;
  }

  _closeSignup({int delay = 0}) async {
    await Future.delayed(Duration(milliseconds: delay));
    Navigator.of(context).pop();
  }

  _returnToCredentials() {
    _pageController.animateToPage(0,
        duration: const Duration(milliseconds: 250), curve: Curves.easeIn);
  }

  _proceedToDetails() {
    _pageController.animateToPage(1,
        duration: const Duration(milliseconds: 250), curve: Curves.easeIn);
  }

If you look at my code, I have a PageView consisting of 2 pages. The PageView pages both use AppBar, and contains the leading back button on the top left.

Normally, pressing the back button on the appbar, or the hardware back button will lead to closing the page, and navigating back to the previous page.

However, since I have WillPopScope, on signup_page, that is overriden. Hence, I'm able to control what I want to happen when the back button (appbar or hardware) is pressed. Which you can see, I can move to the next page view using _proceedToDetails(), or return to the first form using _returnToCredentials(), and close the page if I'm in the first form and back button is pressed, using _closeSignup(), similarly, closing the page even when I'm at the last form if the signup is successful.

Upvotes: 0

Related Questions