我在设置页面中允许用户在运行时更改应用程序主题,但是我遇到了一些问题。
问题是我使用 Riverpod 的共享首选项来存储在我的设置页面中所做的更改,并且每当我更改主题时,我的对话框选择器和设置屏幕就会关闭,并将我带回到主屏幕。
我不希望发生这种情况。我希望用户停留在设置页面并在设置页面本身上查看更改,而不是重置为默认路由。
我已经使用原生 Android 和 Kotlin 构建了应用程序,这是正常行为。
你能帮助我实现同样的目标吗?
下面是我的代码:
class MesMaterialApp extends ConsumerWidget {
MesMaterialApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// Retrieve the router
final router = MesAppRouter.getRouter(
initialLocation: ref.watch(settingsProvider.select((s) => s.isOnboarded))
? HomeRoute.path
: WelcomeRoute.path,
);
// Determine the app brightness (theme)
final brightness = View.of(context).platformDispatcher.platformBrightness;
// Create the text theme
TextTheme textTheme = createTextTheme(context, "Poppins", "Lato");
// Create the app bar theme
AppBarTheme appBarTheme = createAppBarTheme(
brightness == Brightness.light,
);
// Create the material theme
MaterialTheme theme = MaterialTheme(
textTheme,
appBarTheme,
);
// Return the Material App
return MaterialApp.router(
debugShowCheckedModeBanner: false,
// debugShowMaterialGrid: true,
title: 'Flutter Demo',
theme: theme.light(),
darkTheme: theme.dark(),
themeMode: ref.watch(settingsProvider.select(
(s) => s.theme,
)),
highContrastTheme: theme.lightHighContrast(),
highContrastDarkTheme: theme.darkHighContrast(),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
routerConfig: router,
);
}
}
以下是我的路由器代码:
class MesAppRouter {
static GoRouter getRouter({String initialLocation = HomeRoute.path}) {
return GoRouter(
initialLocation: initialLocation,
routes: <RouteBase>[
GoRoute(
name: WelcomeRoute.name,
path: WelcomeRoute.path,
builder: (BuildContext context, GoRouterState state) {
return const WelcomeScreen();
},
),
GoRoute(
name: HomeRoute.name,
path: HomeRoute.path,
pageBuilder: (BuildContext context, GoRouterState state) {
return CustomTransitionPage(
key: state.pageKey,
child: HomeScreen(),
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
return ScaleTransition(
scale: Tween<double>(
begin: 0.95,
end: 1.0,
).animate(animation),
child: child,
);
},
);
},
),
GoRoute(
name: ServicesRoute.name,
path: ServicesRoute.path,
pageBuilder: (BuildContext context, GoRouterState state) {
final String query;
if (state.extra != null) {
final data = state.extra as Map<String, dynamic>;
query = data[ServicesRoute.extraQuery];
// Use data safely here
} else {
query = "";
// Handle case where extra is null
}
return CustomTransitionPage(
key: state.pageKey,
child: ServicesScreen(
searchQuery: query,
),
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
return ScaleTransition(
scale: Tween<double>(
begin: 0.95,
end: 1.0,
).animate(animation),
child: child,
);
},
);
},
),
GoRoute(
name: CycloneReportRoute.name,
path: CycloneReportRoute.path,
pageBuilder: (BuildContext context, GoRouterState state) {
return CustomTransitionPage(
key: state.pageKey,
child: CycloneScreen(),
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
return ScaleTransition(
scale: Tween<double>(
begin: 0.95,
end: 1.0,
).animate(animation),
child: child,
);
},
);
},
),
GoRoute(
name: PrecallRoute.name,
path: PrecallRoute.path,
builder: (BuildContext context, GoRouterState state) {
final data = state.extra! as Map<String, dynamic>;
return PreCallScreen(
service: data[PrecallRoute.extraService],
number: data[PrecallRoute.extraNumber].toString(),
onComplete: () => context.goBack(),
);
},
),
GoRoute(
name: AboutRoute.name,
path: AboutRoute.path,
builder: (BuildContext context, GoRouterState state) {
return const AboutScreen();
},
),
GoRoute(
name: SettingsRoute.name,
path: SettingsRoute.path,
builder: (BuildContext context, GoRouterState state) {
return const SettingsScreen();
},
),
],
);
}
}
显然,问题出在这行代码中:
当然,您需要看看您的
MesAppRouter.getRouter
外观是什么样的,但显然它创建了一个router
当前活动路线成为“主屏幕”的外观。我认为解决方案是变成
MesAppRouter
一个Notifier
类,您可以在其中进行必要的settingsProvider.select((s) => s.isOnboarded)
重定向,但您当前的路线不会因应用程序主题(和其他条件)的变化而重置