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

Lerping between flex_color_scheme-generated themes causes error #9

Closed
Screendead opened this issue Jun 19, 2021 · 5 comments
Closed
Assignees
Labels
bug Flutter This issue can be repeated with Flutter without using this package documentation Improvements or additions to documentation wontfix This issue will not be worked on, a reason for why not is provided in the response.

Comments

@Screendead
Copy link

Description

On iOS, switching between light mode and dark mode (CMD + SHIFT + A for iOS Simulator on macOS) with a flex_color_scheme theme for either theme or darkTheme will cause TextStyle.lerp to fail. This doesn't occur when the vanilla ThemeData.light() and ThemeData.dark() default themes are used.

Minimal Reproducible Example:

import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      darkTheme: FlexColorScheme.dark(
        colors: FlexSchemeColor.from(primary: Colors.blue),
      ).toTheme,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  Widget build(_) => Scaffold(
        appBar: AppBar(
          title: Text('flex_color_scheme MRE'),
        ),
      );
}

Error text

════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building AnimatedTheme(duration: 200ms, dirty, state: _AnimatedThemeState#976ce(ticker active, ThemeDataTween(ThemeData#8c9b4 → ThemeData#47fa6))):
'package:flutter/src/painting/text_style.dart': Failed assertion: line 937 pos 12: 'a == null || b == null || a.inherit == b.inherit': is not true.
2

Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=2_bug.md

The relevant error-causing widget was
MaterialApp
lib/main.dart:9
When the exception was thrown, this was the stack
#2      TextStyle.lerp
package:flutter/…/painting/text_style.dart:937
#3      TextTheme.lerp
package:flutter/…/material/text_theme.dart:690
#4      Typography.lerp
package:flutter/…/material/typography.dart:302
#5      ThemeData.lerp
package:flutter/…/material/theme_data.dart:1530
#6      ThemeDataTween.lerp
package:flutter/…/material/theme.dart:175
...

flutter doctor -v:

[✓] Flutter (Channel stable, 2.0.6, on macOS 11.4 20F71 darwin-x64, locale en-GB)
    • Flutter version 2.0.6 at /Users/jacklusher/dev/flutter
    • Framework revision 1d9032c7e1 (7 weeks ago), 2021-04-29 17:37:58 -0700
    • Engine revision 05e680e202
    • Dart version 2.12.3

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/jacklusher/Library/Android/sdk
    • Platform android-30, build-tools 30.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.5, Build version 12E262
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)

[✓] IntelliJ IDEA Community Edition (version 2021.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 55.1.5
    • Dart plugin version 211.7179

[✓] VS Code (version 1.57.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.23.0

[✓] Connected device (2 available)
    • iPhone 12 Pro Max (mobile) • A1EC90B9-985B-4AF5-A7DC-3961CCBF5D21 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-5 (simulator)
    • Chrome (web)               • chrome                               • web-javascript • Google Chrome 91.0.4472.106
    ! Error: Jack's iPhone XS is busy: Waiting for Device. Xcode will continue when Jack's iPhone XS is finished. (code -10)

• No issues found!
@rydmike
Copy link
Owner

rydmike commented Jun 19, 2021

Thanks Jack @Screendead for the report with the nice minimum reproducible test case.

I think I know what might be causing it. I have seen some mention of a similar issue not related to FlexColorScheme elsewhere.

I actually don't have access to a Mac or physical iOS device, but I think I can setup a test case in the used GitHub actions CI/CD and try to reproduce it there with a cloud Mac build. I should add Mac cloud builds to the final test pipe anyway.

In any case, I might still need your help to verify that the fix works, I'll get back to you later on that.

Did you try also with latest Flutter version 2.2.2? I don't think it actually matters for this though, just curious.

@Screendead
Copy link
Author

Thanks @rydmike for your quick response!

Issue persists on Flutter 2.2.2. On checking with an Android emulator, I can confirm the issue occurs on Android too. To reproduce, open the app, then go to settings and change the theme to dark mode, then switch back to the app and you'll see the error screen flash up briefly.

Happy to help verify a fix.

@rydmike rydmike self-assigned this Jun 23, 2021
@rydmike rydmike added bug Something isn't working documentation Improvements or additions to documentation bug Flutter This issue can be repeated with Flutter without using this package wontfix This issue will not be worked on, a reason for why not is provided in the response. and removed bug Something isn't working labels Jun 23, 2021
@rydmike
Copy link
Owner

rydmike commented Jun 23, 2021

Hi @Screendead what you discovered is actually a bug (of sorts) in the Flutter SDK. I had noticed this myself too while developing FlexColorScheme.

If you try to lerp between two light and dark ThemeData objects that uses text styles where the light and dark theme use different Typography you will get this error. I don't know if it is a bug in the SDK, or by design. Normally you probably don't want to use different Typography for your light and dark theme mode, so it might be this way by design too.

In your example you are running into this situation because you are creating a light theme that uses Flutter SDK default ThemeData, that then by default uses the "wrong" and old Material Typography 2014, whereas FlexColorScheme ThemeData created objects defaults to and use the newer "correct" Material Typography 2018.

In your example, if you replace:

  return MaterialApp(
      darkTheme: FlexColorScheme.dark(
        colors: FlexSchemeColor.from(primary: Colors.blue),
      ).toTheme,

with

  return MaterialApp(
      darkTheme: ThemeData.from(
        colorScheme: ColorScheme.dark(primary: Colors.blue),
      ).copyWith(typography: Typography.material2018()),

You get the same situation and same error with plan vanilla Flutter SDK themes, since it is duplicating the problematic case without usage of FlexColorScheme.


A barebones minimum example of your setup that avoids the issue would be to apply the Typography.material2014() also to the dark theme you define in FlexColorColorScheme, so that its Typography matches the one used by the built-in default ThemeData you get for your light theme mode when you have not defined one:

  return MaterialApp(
      darkTheme: FlexColorScheme.dark(
        colors: FlexSchemeColor.from(primary: Colors.blue),
        typography: Typography.material2014(),
      ).toTheme,

Alternatively you can apply the Typography.material2018() also to the default light theme ThemeData, like so:

  return MaterialApp(
      theme: ThemeData(typography: Typography.material2018()),
      darkTheme: FlexColorScheme.dark(
        colors: FlexSchemeColor.from(primary: Colors.blue),
      ).toTheme,

In both those cases you can now lerp between the light and dark mode. The light and dark modes you get this way still have several different nuances, so I don't recommend matching light and dark mode ThemeData object created this this way.

As a solution for the example, that keeps everything looking nice and also working OK, I would recommend this:

    return MaterialApp(
      theme: FlexColorScheme.light(
        colors: FlexSchemeColor.from(primary: Colors.blue[700]!),
      ).toTheme,
      darkTheme: FlexColorScheme.dark(
        colors: FlexSchemeColor.from(primary: Colors.blue[300]!),
      ).toTheme,

There is a brief mention of this Typography lerping issue in the example 5 tutorial walk through in the docs here:
https://pub.dev/packages/flex_color_scheme#example-5---the-flexcolorscheme-properties-and-toscheme
But it is hidden pretty deep in its advanced features.

I will see what I can do to point it out more in the docs, that if you for some reason just define a dark theme with FlexColorScheme, that while you can, that you then need to adjust the Typography incompatibility with Flutter's old default ThemeData.

The only reason Flutter uses the old typography by default is because Flutter dev team probably did not want to break a lot of legacy apps and tests. So they made the new correct Material typography something you have to configure and opt in manually to in your ThemeData setup.

I on purpose decided to default to the newer Typography in FlexColorScheme. I was thinking that anybody that uses it, will use it to define both their light and dark theme data, and will not see this issue. 😄

There is not much I can do to fix the underlying SDK issue for the use case you presented.

We could file an issue in the Flutter repo. It should in Flutter SDK be possible to take it into consideration via a typography check and skip lerping the light/dark text theme when they use different typography and just switch light/dark text theme without lerp for such use cases. This would be more robust SDK behavior imo. Still Flutter team would probably wonder what the use case is for using different typography in light and dark theme mode... 🤷🏻‍♂️


Conclusion
Other than the above suggested work arounds, or well lets say, advice to use the same Typography in both light and dark theme mode to avoid the issue, there is not much else I can do.

@MarnoDev
Copy link

MarnoDev commented Feb 6, 2022

It Works.

  return MaterialApp(
      darkTheme: ThemeData.from(
        colorScheme: ColorScheme.dark(primary: Colors.blue),
      ),

@rydmike
Copy link
Owner

rydmike commented Feb 6, 2022

Hi @MarnoDev,

Yes that will work, because both the dark and the light theme, via default theme, use the same Typography in the above example.

As shown in this Flutter SDK issue flutter/flutter#89947 (comment)
If light and dark theme use different Typography, it does not work with plain and simple Flutter SDK either.

This example:

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.from(colorScheme: ColorScheme.light(primary: Colors.blue)),
      darkTheme: ThemeData.from(
        colorScheme: ColorScheme.dark(primary: Colors.blue),
      ).copyWith(typography: Typography.material2018()),
      themeMode: ThemeMode.system,
      home: MyHomePage(
        title: 'Flutter Demo Home Page',
        themeMode: ThemeMode.system,
      ),
    );

Will throw an assert error while switching theme mode using device system mode switcher. This is just the way Flutter works at the moment. Read more in the above still open issue on the topic.

The setup that caused the issue discussed in this issue above, created the same underlying setup that also causes an issue in plain vanilla Flutter SDK. FlexColorScheme actually only produces a fancy ThemeData object, so it cannot really do anything to the app theme, that you cannot do and accomplish by constructing the same elaborate ThemeData object manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Flutter This issue can be repeated with Flutter without using this package documentation Improvements or additions to documentation wontfix This issue will not be worked on, a reason for why not is provided in the response.
Projects
None yet
Development

No branches or pull requests

3 participants