[英]How to change the app bar title depending on the selected GoRouter route?
我想使用固定的Scaffold
和AppBar
實現基於 GoRouter 的導航,但根據所選路線動態更改AppBar
的標題。
我正在使用 GoRouter 的ShellRoute
來固定Scaffold
和AppBar
,並嘗試使用 riverpod Provider
更改標題:
final titleProvider = StateProvider((ref) => 'Title');
ShellRoute(
builder: (BuildContext context, GoRouterState state, Widget child) {
return Scaffold(
body: child,
appBar: CustomAppBar()
);
},
routes: [
GoRoute(
path: DashboardScreenWeb.routeLocation,
name: DashboardScreenWeb.routeName,
builder: (context, state) {
ref.read(titleProvider.state).state = DashboardScreenWeb.title;
return const DashboardScreenWeb();
},
),
GoRoute(
path: BusinessDataScreen.routeLocation,
name: BusinessDataScreen.routeName,
builder: (context, state) {
ref.read(titleProvider.state).state = BusinessDataScreen.title;
return const BusinessDataScreen();
},
),
....
我的CustomAppBar
小部件像這樣使用此提供程序:
class CustomAppBar extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
var title = ref.watch(titleProvider);
return new AppBar(
title: Text(title!)
);
}
}
但是,我遇到了很多異常,很可能是因為我在錯誤的時間更改了提供商的 state。 我該怎么辦?
======== Exception caught by widgets library =======================================================
The following StateNotifierListenerError was thrown building Builder(dirty):
At least listener of the StateNotifier Instance of 'StateController<String>' threw an exception
when the notifier tried to update its state.
The exceptions thrown are:
setState() or markNeedsBuild() called during build.
This UncontrolledProviderScope widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
UncontrolledProviderScope
The widget which was currently being built when the offending call was made was:
使用 state 屬性state.location
並將title
傳遞給AppBar
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _shellNavigatorKey = GlobalKey<NavigatorState>();
final router = GoRouter(
initialLocation: '/',
navigatorKey: _rootNavigatorKey,
routes: [
ShellRoute(
navigatorKey: _shellNavigatorKey,
pageBuilder: (context, state, child) {
String title;
switch (state.location) { // 👈 Using state.location to set title
case '/':
title = "Initial Screen";
break;
case '/home':
title = "Home Screen";
break;
default:
title = "Default Screen";
}
return NoTransitionPage(
child: ScaffoldAppAndBottomBar(
appTitle: title, // 👈 pass title here
child: child,
));
},
routes: [
GoRoute(
parentNavigatorKey: _shellNavigatorKey,
path: '/home',
name: 'Home Title',
pageBuilder: (context, state) {
return const NoTransitionPage(
child: Scaffold(
body: Center(
child: Text("Home"),
),
),
);
},
),
GoRoute(
path: '/',
name: 'App Title',
parentNavigatorKey: _shellNavigatorKey,
pageBuilder: (context, state) {
return const NoTransitionPage(
child: Scaffold(
body: Center(child: Text("Initial")),
),
);
},
),
],
),
],
);
class CustomAppBar extends StatelessWidget {
Widget child;
String? appTitle;
CustomAppBar(
{super.key, required this.child, required this.appTitle});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(appTitle ?? "Default"),
),
body: SafeArea(child: child),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.go('/home');
},
child: const Icon(Icons.home),
),
);
}
}
Output:
你應該這樣定義你的 titleProvider:
final titleProvider = Provider<String>((ref) => 'Title');
並更新提供者:
GoRoute( path: BusinessDataScreen.routeLocation, name: BusinessDataScreen.routeName, builder: (context, state) { return ProviderScope( overrides: [ titleProvider.overrideWithValue('youTitleHere') ] child: const BusinessDataScreen(), ); }, ),
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.