大家好,我在 Flutter 应用程序中处理 Android 上的后退手势(后退按钮)时遇到问题。例如,我有一个使用 Navigator 的 pushNamed 功能推送的屏幕(登录屏幕是从欢迎屏幕推送的)。在该屏幕中,我希望应用程序返回到上一个屏幕,但应用程序却关闭了。这是代码。
路由器类
class AppRouter {
Route<dynamic>? onGenerateRoute(RouteSettings routeSettings) {
switch (routeSettings.name) {
case '/login':
return PageRouteBuilder(
settings: routeSettings,
pageBuilder: (_, __, ___) {
return const LoginScreen();
},
// Pass this to make popUntil(), pushNamedAndRemoveUntil(), works
transitionDuration: const Duration(milliseconds: 600),
reverseTransitionDuration: const Duration(milliseconds: 450),
transitionsBuilder: (_, a, __, c) => SlideTransition(
position: Tween<Offset>(
begin: const Offset(1.0, 0.0), // From bottom
end: Offset.zero,
).animate(
CurvedAnimation(
parent: a,
curve: Curves.easeInOutCubicEmphasized,
),
),
child: c));
default:
return _materialRoute(const WelcomeScreen());
}
}
static Route<dynamic> _materialRoute(Widget view) {
return MaterialPageRoute(builder: (_) => view);
}
}
main.dart
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.edgeToEdge,
);
return ScreenUtilInit(
designSize: const Size(430, 932),
minTextAdapt: true,
splitScreenMode: true,
builder: (_, child) {
return MaterialApp(
home: Navigator(
key: navigatorKey,
onGenerateRoute: AppRouter().onGenerateRoute,
),
);
});
}
}
欢迎屏幕
class WelcomeScreen extends StatefulWidget {
const WelcomeScreen({super.key});
@override
State<StatefulWidget> createState() {
return _WelcomeScreenState();
}
}
class _WelcomeScreenState extends State<WelcomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
Navigator.of(context).pushNamed('/login');
},
child: const Text('Continue with E-Mail'),
),
),
const SizedBox(
height: 12,
),
],
),
),
),
);
}
}
登录屏幕
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<StatefulWidget> createState() {
return _LoginScreenState();
}
}
class _LoginScreenState extends State<LoginScreen> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: true,
onPopInvoked: (didPop) => print('onPopInvoked didPop? $didPop'),
child: Scaffold(
appBar: AppBar(
toolbarHeight: 0.09.sh,
leadingWidth: 70,
leading: Padding(
padding: const EdgeInsets.only(left: 20),
child: GestureDetector(
onTap: () {
Navigator.of(context).pushReplacementNamed('/welcome');
},
child: SvgPicture.asset(
'assets/icons/back-in-circle.svg',
fit: BoxFit.contain,
color: Theme.of(context).brightness == Brightness.light
? colorBlack
: null,
),
),
)),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Text("Login screen")
],
),
),
),
),
);
}
}
已将以下行添加到 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
<application
...
<activity
...
android:enableOnBackInvokedCallback="true">
您在
pushReplacementNamed
中使用 LoginScreen
而不是 pop
。
pushReplacementNamed
将当前路线替换为新路线。这就是应用程序关闭而不是返回欢迎屏幕的原因。