gpt4 book ai didi

android - Android 上的 Flutter 嵌套导航后退按钮处理

转载 作者:行者123 更新时间:2023-12-05 00:00:27 33 4
gpt4 key购买 nike

背景

我的 InitialPage 上有一个 Navigator 小部件,我将两条路线推到它上面(NestedFirstRouteNestedSecondRoute)。当我在 Android 上按下物理后退按钮时,导航器中的两条路线都会弹出(这是预期的)。

用例

所以我想在按下后退按钮时处理这种情况,只有顶部路由(NestedSecondRoute)必须弹出。

我试过的解决方案

为了处理这个问题,我将 Navigator 小部件包装在 WillPopScope 中处理后退按钮按下事件并将键分配给嵌套路由,以便在 willPop 范围内弹出路由时使用它们。

我在这条线上遇到异常

if (NestedFirstPage.firstPageKey.currentState!.canPop()) {

Exception has occurred.
_CastError (Null check operator used on a null value)

这是最小和完整的代码示例

import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
final _navigatorKey = GlobalKey<NavigatorState>();
@override
Widget build(BuildContext context) {
return MaterialApp(
onGenerateRoute: (settings) {
switch (settings.name) {
case NestedFirstPage.route:
return MaterialPageRoute(
builder: (context) {
return WillPopScope(
onWillPop: () async {
if (NestedFirstPage.firstPageKey.currentState!.canPop()) {
NestedFirstPage.firstPageKey.currentState!.pop();
return false;
} else if (NestedSecondPage.secondPageKey.currentState!
.canPop()) {
NestedSecondPage.secondPageKey.currentState!.pop();
return false;
}
return true;
},
child: Navigator(
key: _navigatorKey,
onGenerateRoute: (settings) {
switch (settings.name) {
case Navigator.defaultRouteName:
return MaterialPageRoute(
builder: (context) => const NestedFirstPage(),
settings: settings,
);
case NestedSecondPage.route:
return MaterialPageRoute(
builder: (context) => const NestedSecondPage(),
settings: settings,
);
}
},
),
);
},
settings: settings,
);
}
},
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const InitialPage(title: 'Initial Page'),
);
}
}

class InitialPage extends StatelessWidget {
const InitialPage({Key? key, required this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
OutlinedButton(
onPressed: () {
Navigator.pushNamed(context, NestedFirstPage.route);
},
child: const Text('Move to Nested First Page'),
),
],
),
),
);
}
}

class NestedFirstPage extends StatelessWidget {
const NestedFirstPage({Key? key}) : super(key: key);

static final GlobalKey<NavigatorState> firstPageKey =
GlobalKey<NavigatorState>();
static const String route = '/nested/first';

@override
Widget build(BuildContext context) {
return Scaffold(
key: firstPageKey,
appBar: AppBar(title: const Text('Nested First Page')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('First page'),
OutlinedButton(
child: const Text('Move to Nested Second Page'),
onPressed: () {
Navigator.pushNamed(context, NestedSecondPage.route);
},
),
],
),
),
);
}
}

class NestedSecondPage extends StatelessWidget {
const NestedSecondPage({Key? key}) : super(key: key);
static final GlobalKey<NavigatorState> secondPageKey =
GlobalKey<NavigatorState>();
static const String route = '/nested/second';

@override
Widget build(BuildContext context) {
return Scaffold(
key: secondPageKey,
appBar: AppBar(title: const Text('Nested Second Page')),
body: const Center(
child: Text('Second Page'),
),
);
}
}

最佳答案

这是对上述代码稍作修改的版本,它将允许推送嵌套路由并可以通过 android 后退按钮弹出

import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
routes: {
'/nested/first': (context) => const NestedFirstPage(),
'/nested/first/second': (context) => const NestedSecondPage()
},
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const RouteManager());
}
}

class InitialPage extends StatelessWidget {
const InitialPage({Key? key, required this.title}) : super(key: key);
final String title;
static const String route = '/';
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (navigatorKey.currentState != null &&
navigatorKey.currentState!.canPop()) {
navigatorKey.currentState!.pop();
return true;
}
return false;
},
child: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
OutlinedButton(
onPressed: () {
navigate(context, NestedFirstPage.route);
},
child: const Text('Move to Nested First Page'),
),
],
),
),
),
);
}
}

Future<void> navigate(BuildContext context, String route,
{bool isDialog = false, bool isRootNavigator = true}) =>
Navigator.of(context, rootNavigator: isRootNavigator).pushNamed(route);

final navigatorKey = GlobalKey<NavigatorState>();

class RouteManager extends StatelessWidget {
const RouteManager({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
switch (settings.name) {
case '/nested/first':
builder = (BuildContext _) => const NestedFirstPage();
break;
case '/nested/first/second':
builder = (BuildContext _) => const NestedSecondPage();
break;
default:
builder =
(BuildContext _) => const InitialPage(title: 'Initial Page');
}
return MaterialPageRoute(builder: builder, settings: settings);
});
}
}

class NestedFirstPage extends StatelessWidget {
static final GlobalKey<NavigatorState> firstPageKey =
GlobalKey<NavigatorState>();
static const String route = '/nested/first';

const NestedFirstPage({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
key: firstPageKey,
appBar: AppBar(title: const Text('Nested First Page')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('First page'),
OutlinedButton(
child: const Text('Move to Nested Second Page'),
onPressed: () {
navigate(context, NestedSecondPage.route);
},
),
],
),
),
);
}
}

class NestedSecondPage extends StatelessWidget {
const NestedSecondPage({Key? key}) : super(key: key);
static final GlobalKey<NavigatorState> secondPageKey =
GlobalKey<NavigatorState>();
static const String route = '/nested/first/second';

@override
Widget build(BuildContext context) {
return Scaffold(
key: secondPageKey,
appBar: AppBar(title: const Text('Nested Second Page')),
body: const Center(
child: Text('Second Page'),
),
);
}
}

这是一个 real world example带有嵌套的底部导航栏。

关于android - Android 上的 Flutter 嵌套导航后退按钮处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72126549/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com