后退按钮拦截器在代码中不起作用。我也尝试过 PopScope,但还没有工作。我不想退出应用程序,只是重定向到上一页。为此我需要什么?比如我需要提供家长路线什么的吗?
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(),
),
],
),
);
}
}
这里是后退按钮拦截器包的代码。虽然主图标可以工作,但系统或电话的按钮不起作用
当你使用appRouter.go时,你将无法返回,返回需要使用.push/.pushNamed导航
final GoRouter appRouter = GoRouter(
// redirect: _handleRedirect,
routes: <RouteBase>[...],
)
导航:
appRouter.push("/home");
回去
void popIfPossible() {
try {
// canPop Might throw exception if used too early
if (appRouter.canPop()) appRouter.pop();
} catch (_) {
appRouter.go(AppRoutes.defaultNotUsed);
}
}
使用
didPopRoute
处理后退按钮:
@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
}
}
& 与
GoRouter
配合使用效果很好。
具体代码:
@override
Future<bool> didPopRoute() {
return Future.value(true);
}
官方文档:
Flutter > widgets.dart > WidgetsBindingObserver > didPopRoute 方法