Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Material Dark Theme Overrides Cupertino Dark Theme on iOS #420

Open
LeonManolo opened this issue Jun 21, 2023 · 3 comments
Open

Material Dark Theme Overrides Cupertino Dark Theme on iOS #420

LeonManolo opened this issue Jun 21, 2023 · 3 comments

Comments

@LeonManolo
Copy link

LeonManolo commented Jun 21, 2023

Hello,

I've encountered an issue when using both the Material dark theme and Cupertino dark theme simultaneously on iOS. Specifically, the Material dark theme appears to override
the Cupertino dark theme, as shown in the attached screenshot

Here's a snippet of the relevant code:

class AppView extends StatelessWidget {
  const AppView({super.key});

  @override
  Widget build(BuildContext context) {
    return PlatformProvider(
      settings: PlatformSettingsData(
        iosUsesMaterialWidgets: true,
      ),
      builder: (context) => PlatformTheme(
        themeMode: ThemeMode.system,
        materialLightTheme: const LightMaterialAppTheme().themeData,
        materialDarkTheme: const DarkMaterialAppTheme().themeData,
        cupertinoLightTheme: const LightCupertinoAppTheme().themeData,
        cupertinoDarkTheme: MaterialBasedCupertinoThemeData(
          materialTheme: ThemeData.dark().copyWith(
            cupertinoOverrideTheme: CupertinoThemeData(
              primaryColor: CupertinoColors.systemRed, // as an example
              // more theme data...
            ),
          ),
        ),
        // rest of the code...
      ),
    );
  }
}

In this setup, the primary color should be red. However, as demonstrated in the screenshot, this is not the case. This issue does not occur on Android, nor does it occur with the light mode themes where the Cupertino theme isn't overridden by the Material theme.

The only workaround I've found is to conditionally set the Material dark theme to null on iOS, as shown in the following code snippet:

class AppView extends StatelessWidget {
  const AppView({super.key});

  @override
  Widget build(BuildContext context) {
    return PlatformProvider(
      settings: PlatformSettingsData(
        iosUsesMaterialWidgets: true,
        //iosUseZeroPaddingForAppbarPlatformIcon: true,
      ),
      builder: (context) => PlatformTheme(
        themeMode: ThemeMode.system,
        materialLightTheme: const LightMaterialAppTheme().themeData,
        materialDarkTheme:
        // temporary fix, because material dark mode overrides cupertino dark mode
            Platform.isAndroid ? const DarkMaterialAppTheme().themeData : null,
        cupertinoLightTheme: const LightCupertinoAppTheme().themeData,
        cupertinoDarkTheme: MaterialBasedCupertinoThemeData(
          materialTheme: ThemeData.dark().copyWith(
            cupertinoOverrideTheme: CupertinoThemeData(
              primaryColor: CupertinoColors.systemIndigo,
              barBackgroundColor:
              CupertinoThemeData(brightness: Brightness.dark).barBackgroundColor,
              scaffoldBackgroundColor: CupertinoColors.systemBackground,
              textTheme: CupertinoTextThemeData(
                textStyle: CupertinoThemeData(brightness: Brightness.dark).textTheme.textStyle,
                navActionTextStyle: CupertinoThemeData(brightness: Brightness.dark)
                    .textTheme.navActionTextStyle
                    .copyWith(color: const Color(0xF0F9F9F9)),
                navLargeTitleTextStyle: CupertinoThemeData(brightness: Brightness.dark)
                    .textTheme.navLargeTitleTextStyle
                    .copyWith(color: const Color(0xF0F9F9F9)),
              ),
            ),
          ),
        ),
        matchCupertinoSystemChromeBrightness: false,
        builder: (context) => PlatformApp(
          // needed to get the cupertino modal shrink effect
          onGenerateRoute: (settings) => MaterialWithModalsPageRoute(
            builder: (context) => FlowBuilder<AppStatus>(
              state: context.select((AppBloc bloc) => bloc.state.status),
              onGeneratePages: onGenerateAppViewPages,
            ),
          ),
          localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
            DefaultMaterialLocalizations.delegate,
            DefaultWidgetsLocalizations.delegate,
            DefaultCupertinoLocalizations.delegate,
          ],
        ),
      ),
    );
  }
}

This workaround allows the Cupertino dark theme to render correctly:

Any guidance or suggestions for addressing this issue would be greatly appreciated, thanks!

@aqwert
Copy link
Collaborator

aqwert commented Jun 23, 2023

What version of the package are you using. There was a fix around this area with v3.3.4. See #402

@LeonManolo
Copy link
Author

Thats the version Im using:
flutter_platform_widgets: ^3.3.4

@Dark-Schneider-666
Copy link

Dark-Schneider-666 commented Aug 14, 2024

Still happens using version 7.0.1. Currently I fixed this using this function when creating the app:

// fixes the current bug of PlatformTheme with materialDarkTheme overriding cupertinoDarkTheme
  ThemeData? getMaterialThemeData(Brightness brightness) {
    if (Platform.isIOS) {
      return null;
    } else {
      return switch (brightness) {
        Brightness.dark => ThemeData.dark(),
        Brightness.light => ThemeData.light(),
      };
    }
  }

Then construct with:

@override
Widget build(BuildContext context) {
    return PlatformProvider(
        builder: (context) => PlatformTheme(
          themeMode: ThemeMode.system,
          cupertinoDarkTheme:
              const CupertinoThemeData(brightness: Brightness.dark),
          cupertinoLightTheme:
              const CupertinoThemeData(brightness: Brightness.light),
          materialDarkTheme: getMaterialThemeData(Brightness.dark),
          materialLightTheme: getMaterialThemeData(Brightness.light),
          builder: (context) => PlatformApp(
...

With this, the app uses the system theme and adapts to the device theme system setting if changed. Noticed that if not defined the values it always uses the Light mode by default.

But I think all the setting the ThemeMode.system and setting manually the system light and dark mode should be made by default by the PlatformTheme by its own.

This can be achieved in a single call with something like this:

import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';

PlatformTheme platformThemeSystem({required WidgetBuilder builder}) {
  return PlatformTheme(
    builder: builder,
    themeMode: ThemeMode.system,
    cupertinoDarkTheme: const CupertinoThemeData(brightness: Brightness.dark),
    cupertinoLightTheme: const CupertinoThemeData(brightness: Brightness.light),
    materialDarkTheme: Platform.isIOS ? null : ThemeData.dark(),
    materialLightTheme: Platform.isIOS ? null : ThemeData.light(),
  );
}

Then just:

@override
Widget build(BuildContext context) {
    return PlatformProvider(
        builder: (context) => platformThemeSystem(
          builder: (context) => PlatformApp(
...

Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants