skip to Main Content

The backbutton interceptor is not working in the code. i also tried with PopScope, but not working yet. I don’t want to exit the app ,just redirect to previous page. For this what I need? Like do I need to provide ay parent route or something ?

class Checklist extends StatefulWidget {
  const Checklist({super.key});

  @override
  _ChecklistState createState() => _ChecklistState();
}

class _ChecklistState extends State<Checklist> {
  @override
  void initState() {
    super.initState();
    
    Provider.of<checkListProvider>(context, listen: false).loadData();
    
    BackButtonInterceptor.add(_onBackPressed);
  }

  @override
  void dispose() {
    
    BackButtonInterceptor.remove(_onBackPressed);
    super.dispose();
  }

  bool _onBackPressed(bool stopDefaultButtonEvent, RouteInfo info) {
   
    _showExitDialog();
    return true; 
  }

  Future<void> _showExitDialog() async {
    final shouldPop = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Confirm Exit'),
        content: const Text('Do you want to go back to the previous screen?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(false),
            child: const Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              Navigator.of(context).pop(true);
              GoRouter.of(context).pop(); // Go back to the previous route
            },
            child: const Text('Yes'),
          ),
        ],
      ),
    );

    if (shouldPop ?? false) {
      GoRouter.of(context).pop();
    }
  }

  @override
  Widget build(BuildContext context) {
    final pageState = Provider.of<PageState>(context);
    final titleProvider = Provider.of<PageTitle>(context);
    final title =
        titleProvider.title.isNotEmpty ? titleProvider.title : 'Default Title';

    final checkProvider = Provider.of<checkListProvider>(context);

    return Scaffold(
      backgroundColor: Colors.teal[50],
      appBar: AppBar(
        backgroundColor: Colors.teal[50],
        title: Center(child: Text(title)),
        leading: IconButton(
          icon: const Icon(Icons.chevron_left_outlined),
          onPressed: () {
            pageState.setRoute('/help-center');
            GoRouter.of(context).pop('/help-center');
          },
        ),
      ),
      body: checkProvider.isLoading
          ? const Center(child: CircularProgressIndicator())
          : checkProvider.errorMessage.isNotEmpty
              ? Center(child: Text(checkProvider.errorMessage))
              : ListView(
                  padding: const EdgeInsets.all(10),
                  children: [
                    ExpansionTile(
                      title: const Text('Completed'),
                      children: checkProvider.completed
                          .map((item) => ListTile(
                                title: Text(item['title']),
                                subtitle: Text(item['description']),
                              ))
                          .toList(),
                    ),
                    ExpansionTile(
                      title: const Text('Next'),
                      children: checkProvider.next
                          .map(
                            (item) => CheckboxListTile(
                              checkColor: Colors.teal[500],
                              checkboxShape: const CircleBorder(),
                              title: Text(item['title']),
                              subtitle: Text(item['description']),
                              value: item['completed'],
                              onChanged: (val) {
                                if (val == true) {
                                  checkProvider.toogleComplete(item, 'next');
                                }
                              },
                            ),
                          )
                          .toList(),
                    ),
                    ExpansionTile(
                      title: const Text('Upcoming'),
                      children: checkProvider.upcoming
                          .map(
                            (item) => CheckboxListTile(
                              checkColor: Colors.teal[500],
                              checkboxShape: const CircleBorder(),
                              title: Text(item['title']),
                              subtitle: Text(item['description']),
                              value: item['completed'],
                              onChanged: (val) {
                                if (val == true) {
                                  checkProvider.toogleComplete(
                                      item, 'upcoming');
                                }
                              },
                            ),
                          )
                          .toList(),
                    ),
                  ],
                ),
    );
  }
}

Here is the code for backbutton interceptor package. Though the leading icon is working, the system or phone’s button is not working

2

Answers


  1. When you use appRouter.go, you will not be able to return, to return you need to navigate with .push/.pushNamed

    final GoRouter appRouter = GoRouter(
     // redirect: _handleRedirect,
      routes: <RouteBase>[...],
    )
    

    Navigate:

    appRouter.push("/home");
    

    go back

    void popIfPossible() {
      try {
        // canPop Might throw exception if used too early
        if (appRouter.canPop()) appRouter.pop();
      } catch (_) {
        appRouter.go(AppRoutes.defaultNotUsed);
      }
    }
    
    Login or Signup to reply.
  2. Use didPopRoute to handle back button:

    @override
    Future<bool> didPopRoute() {
      bool shouldAllowBack = true; // Update condition if required
      if (shouldAllowBack) {
        return super.didPopRoute(); // allow back
      } else {
        // Add logic here if required
        return Future.value(true);  // back not allowed
      }
    }
    

    & It works fine with GoRouter.

    Exact code:

    @override
    Future<bool> didPopRoute() {
      return Future.value(true);
    }
    

    Official Documentaion:
    Flutter > widgets.dart > WidgetsBindingObserver > didPopRoute method


    In case of not working:

    • Extend the State class with WidgetsBindingObserver
    class Home extends State with WidgetsBindingObserver {
    
    }
    
    • Register and unregister the observer
    @override
    void initState() {
      super.initState();
      // Add this widget as an observer
      WidgetsBinding.instance.addObserver(this);
    }
    
    @override
    void dispose() {
      // Remove this widget as an observer
      WidgetsBinding.instance.removeObserver(this);
      super.dispose();
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search