| // Copyright 2014 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // This sample demonstrates showing a confirmation dialog before navigating | |
| // away from a page. | |
| import 'package:flutter/material.dart'; | |
| void main() => runApp(const NavigatorPopHandlerApp()); | |
| class NavigatorPopHandlerApp extends StatelessWidget { | |
| const NavigatorPopHandlerApp({super.key}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| initialRoute: '/home', | |
| routes: <String, WidgetBuilder>{ | |
| '/home': (BuildContext context) => const _HomePage(), | |
| '/two': (BuildContext context) => const _PageTwo(), | |
| }, | |
| ); | |
| } | |
| } | |
| class _HomePage extends StatefulWidget { | |
| const _HomePage(); | |
| @override | |
| State<_HomePage> createState() => _HomePageState(); | |
| } | |
| class _HomePageState extends State<_HomePage> { | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| body: Center( | |
| child: Column( | |
| mainAxisAlignment: .center, | |
| children: <Widget>[ | |
| const Text('Page One'), | |
| TextButton( | |
| onPressed: () { | |
| Navigator.of(context).pushNamed('/two'); | |
| }, | |
| child: const Text('Next page'), | |
| ), | |
| ], | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| class _PageTwo extends StatefulWidget { | |
| const _PageTwo(); | |
| @override | |
| State<_PageTwo> createState() => _PageTwoState(); | |
| } | |
| class _PageTwoState extends State<_PageTwo> { | |
| /// Shows a dialog and resolves to true when the user has indicated that they | |
| /// want to pop. | |
| /// | |
| /// A return value of null indicates a desire not to pop, such as when the | |
| /// user has dismissed the modal without tapping a button. | |
| Future<bool?> _showBackDialog() { | |
| return showDialog<bool>( | |
| context: context, | |
| builder: (BuildContext context) { | |
| return AlertDialog( | |
| title: const Text('Are you sure?'), | |
| content: const Text('Are you sure you want to leave this page?'), | |
| actions: <Widget>[ | |
| TextButton( | |
| style: TextButton.styleFrom( | |
| textStyle: Theme.of(context).textTheme.labelLarge, | |
| ), | |
| child: const Text('Nevermind'), | |
| onPressed: () { | |
| Navigator.pop(context, false); | |
| }, | |
| ), | |
| TextButton( | |
| style: TextButton.styleFrom( | |
| textStyle: Theme.of(context).textTheme.labelLarge, | |
| ), | |
| child: const Text('Leave'), | |
| onPressed: () { | |
| Navigator.pop(context, true); | |
| }, | |
| ), | |
| ], | |
| ); | |
| }, | |
| ); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| body: Center( | |
| child: Column( | |
| mainAxisAlignment: .center, | |
| children: <Widget>[ | |
| const Text('Page Two'), | |
| PopScope<Object?>( | |
| canPop: false, | |
| onPopInvokedWithResult: (bool didPop, Object? result) async { | |
| if (didPop) { | |
| return; | |
| } | |
| final bool shouldPop = await _showBackDialog() ?? false; | |
| if (context.mounted && shouldPop) { | |
| Navigator.pop(context); | |
| } | |
| }, | |
| child: TextButton( | |
| onPressed: () async { | |
| final bool shouldPop = await _showBackDialog() ?? false; | |
| if (context.mounted && shouldPop) { | |
| Navigator.pop(context); | |
| } | |
| }, | |
| child: const Text('Go back'), | |
| ), | |
| ), | |
| ], | |
| ), | |
| ), | |
| ); | |
| } | |
| } |