admin管理员组

文章数量:1323730

I have in my settings page the ability for the user to change the app theme at runtime, but I am running into some problems.

The problem that I am using shared preferences with Riverpod to store the changes made in my settings page and whenever I change the theme, my dialog selector and settings screen closes, and it takes me back to the home screen.

I don't want that to happen. I want the user to stay on the settings page and see the changes on the settings page itself, rather than resetting to the default route.

I've built apps using native android and Kotlin, and this was the normal behavior there.

Can you help me achieve the same thing here?

Below is my code:

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,
    );
  }
}

Below is my router code:

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();
          },
        ),
      ],
    );
  }
}

I have in my settings page the ability for the user to change the app theme at runtime, but I am running into some problems.

The problem that I am using shared preferences with Riverpod to store the changes made in my settings page and whenever I change the theme, my dialog selector and settings screen closes, and it takes me back to the home screen.

I don't want that to happen. I want the user to stay on the settings page and see the changes on the settings page itself, rather than resetting to the default route.

I've built apps using native android and Kotlin, and this was the normal behavior there.

Can you help me achieve the same thing here?

Below is my code:

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,
    );
  }
}

Below is my router code:

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();
          },
        ),
      ],
    );
  }
}
Share Improve this question edited Jan 12 at 15:34 Mervin Hemaraju asked Jan 12 at 6:04 Mervin HemarajuMervin Hemaraju 2,1873 gold badges37 silver badges87 bronze badges 2
  • Is MesAppRouter instance getting rebuilt perhaps? That would lose your place in the app. – Randal Schwartz Commented Jan 12 at 7:16
  • I think it's my settings provider because if i comment it out, it doesn't get rebuilt. But then how will i update the settings? – Mervin Hemaraju Commented Jan 12 at 7:38
Add a comment  | 

1 Answer 1

Reset to default 1

Apparently, the problem is in this line of code:

  @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,
    );

Of course, you need to look at what your MesAppRouter.getRouter looks like, but apparently it creates a router in which the current active route becomes "home screen".

I assume that the solution would be to turn MesAppRouter into a Notifier class, in which you could make the necessary settingsProvider.select((s) => s.isOnboarded) redirects, but your current route would not be reset by changes in the application theme (and other conditions)

本文标签: riverpodChanging app theme in flutter resets the whole app stateStack Overflow