Mervin Hemaraju
Mervin Hemaraju

Reputation: 2117

Flutter platform brightness irregularities

In my flutter app, I allow user to change the theme of the app using either Follow System, Light or Dark theme.

But the status bar color doesn't change appropriately. My status bar icon color always stays white (Which means when set to light theme, it becomes invisible).

I even tried the below which didn't work:

// Determine the app brightness (theme)
final brightness = PlatformDispatcher.instance.platformBrightness;

print("Brightness: $brightness");

SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
  statusBarIconBrightness: brightness == Brightness.dark
      ? Brightness.light
      : Brightness.dark, // status bar color
));

I then realized this through my print log:

Irrespective of my app theme, when the system UI (in my phone settings) itself is set to light theme, whether i choose follow_system, light or dark in my app, it always returns Brightness.Light and when the system UI itself is set to dark theme, it always returns Brightness.Dark

Is this a normal behavior or am i doing something wrong ?

Below is just a reference how i initialize my MaterialApp:

  ThemeData light() {
return theme(const ColorScheme(
  brightness: Brightness.light,
  primary: ....,
  )
)

ThemeData dark() {
return theme(const ColorScheme(
  brightness: Brightness.dark,
  primary: ....,
  )
)

ThemeData lightHighContrast() {
return theme(const ColorScheme(
  brightness: Brightness.light,
  primary: ....,
  )
)

ThemeData darkHighContrast() {
return theme(const ColorScheme(
  brightness: Brightness.dark,
  primary: ....,
  )
)


ThemeData theme(ColorScheme colorScheme) => ThemeData(
    useMaterial3: true,
    brightness: colorScheme.brightness,
    colorScheme: colorScheme,
    appBarTheme: appBarTheme,
    textTheme: textTheme.apply(
      bodyColor: colorScheme.onSurface,
      displayColor: colorScheme.onSurface,
    ),
    scaffoldBackgroundColor: colorScheme.surface,
    canvasColor: colorScheme.surface,
  );


class MesMaterialApp extends ConsumerWidget {
  MesMaterialApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Get the initial location
    final intitialLocation =
        ref.watch(settingsProvider.select((s) => s.isOnboarded))
            ? HomeRoute.path
            : WelcomeRoute.path;

    // Set the initial location
    MesAppRouter.instance.setInitialLocation(intitialLocation);

    // Get the router instance
    final router = MesAppRouter.instance.getRouter();

    // Determine the app brightness (theme)
    final brightness = PlatformDispatcher.instance.platformBrightness;

    print("Brightness: $brightness");

    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
      statusBarIconBrightness: brightness, // status bar icons' color
      statusBarColor: brightness == Brightness.dark
          ? Colors.white
          : Colors.black, // status bar color
    ));

    // Create the text theme
    TextTheme textTheme = createTextTheme(context, "Poppins", "Lato");

    // Create the app bar theme
    AppBarTheme appBarTheme = createAppBarTheme(brightness);

    // Create the material theme
    MaterialTheme theme = MaterialTheme(
      textTheme,
      appBarTheme,
    );

    // Return the Material App
    return MaterialApp.router(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: theme.light(),
      darkTheme: theme.dark(),
      highContrastTheme: theme.lightHighContrast(),
      highContrastDarkTheme: theme.darkHighContrast(),
      themeMode: ref.watch(settingsProvider.select(
        (s) => s.theme,
      )),
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: AppLocalizations.supportedLocales,
      locale: ref.watch(settingsProvider.select(
        (s) => s.locale == MesLocale.system ? null : Locale(s.locale.lang),
      )),
      routerConfig: router,
    );
  }
}

Upvotes: 0

Views: 40

Answers (1)

nifesi
nifesi

Reputation: 160

class BrightnessExample extends StatefulWidget {
  const BrightnessExample({super.key});

    @override
    State<BrightnessExample> createState() => _BrightnessExampleState();
 }

class _BrightnessExampleState extends State<BrightnessExample>
  with WidgetsBindingObserver {

@override
 void initState() {
 super.initState();
 WidgetsBinding.instance.addObserver(this);
}

 Brightness get platformBrightness {
     return WidgetsBinding.instance.platformDispatcher.platformBrightness;
 }

 @override
 void didChangePlatformBrightness() {
   super.didChangePlatformBrightness();
   // CHANGE SYSTEM STATUS BAR HERE ACCRODINLY WITH PLATFROM BRIGHNESS
 }


 @override
 Widget build(BuildContext context) {
     return const Placeholder();
 }
}

Here’s how you can use the WidgetsBindingObserver mixin to detect platform brightness changes and update the app’s status bar accordingly.

First, add the WidgetsBindingObserver mixin to your State class.

Register the WidgetsBindingObserver in the initState method to start listening for platform changes.

Create a simple getter to fetch the current platform brightness, and override didChangePlatformBrightness to handle brightness changes dynamically.

Upvotes: 0

Related Questions