rydmike / flex_color_scheme

A Flutter package to make and use beautiful color scheme based themes.
Other
947 stars 105 forks source link

material 3 app bar color #197

Closed bksubhuti closed 11 months ago

bksubhuti commented 11 months ago

We are now up to 3.2k active installs on tipitaka pali reader. (buddhist sun ~500).. and then other os's maybe 800. I just implemented useMaterial3: true, and it works really nice. There is not much to do for this conversion, but make the cards a little tighter and some search filter chips were hardcoded as blue which we can fix. I didn't know material 3 this was possible until the play store console app recently updated.

The app title "TIpitaka Pali Reader" should have the app bar theme color (in m2 it does). The book title should have the app bar theme color (in m2 it does). I was wondering if there is a way to get the app bar back to have a material 3 style color other than white???

Much appreciation for you color theme package.

Screenshot_20231013-143938

Screenshot_20231013-143837

bksubhuti commented 11 months ago

What I would like is either the floating action button color or the bottom navbar color or the card color. However, I tried adding the colors based on those themes but they are white.

rydmike commented 11 months ago

Hi @bksubhuti,

With FlexColorScheme you can nowadays theme pretty much any widget to use any color from your theme's ColorScheme. In Material-3 the AppBar is surface colored by default, but you can set it to primary like in Material-2.

Change it either via the older API and more limited color options directly in FlexThemeData or FlexColorScheme:

theme: FlexThemeData.light(
  scheme: FlexScheme.barossa,
  appBarStyle: FlexAppBarStyle.primary,  
  useMaterial3: true,
),

Screenshot 2023-10-13 at 17 49 44

Or via the newer FlexSubThemesData API:

theme: FlexThemeData.light(
  scheme: FlexScheme.barossa,
  subThemesData: const FlexSubThemesData(
    appBarBackgroundSchemeColor: SchemeColor.primary,
  ),
  useMaterial3: true,
),

Note that FlexThemeData.light is just newer shorthand for FlexColorScheme.light(...).toTheme, so the above can just as well be written as:

theme: FlexColorScheme.light(
  scheme: FlexScheme.barossa,
  subThemesData: const FlexSubThemesData(
    appBarBackgroundSchemeColor: SchemeColor.primary,
  ),
  useMaterial3: true,
).toTheme,

Screenshot 2023-10-13 at 17 50 39

With the newer API above you can use any of your theme's ColorScheme color as AppBar color.

Material 3 AppBar Info Do be aware that Material3 also uses elevation tint on the AppBar, which is based on ColorScheme.surfaceTint, which equals primary by default. To avoid the elevation tint elevation and scroll under elevation to zero. Or set the app bar elevation tint color to Colors.transparent. If you want to use elevation and show a shadow on App Bar in M3, you need to set its shadowColor to Colors.black.

You will need to define desired color separately the AppBar's light and dark themes.

ColorScheme M3 info In Material 2, the role of secondary color is basically moved to the tertiary color. When you change to Material 3 form Material 2, what often works is to put your Material 2 secondary color as tertiary color, and add a new color for secondary color. Typically (by default in M3) this color is a more muted, less colorful version of your primary color. With Material 3 using a seeded color scheme usually works best and then locking the primary color down to your seed color to use it as brand color in light mode. If this brand color is important in dark mode, it can often be used as the primaryVariant color


Latest version of Themes Playground where you can try different themes and see what code it makes for the theme and even copy paste the code can be found here: https://rydmike.com/flexcolorscheme/themesplayground-latest/

The FlexColorScheme docs also contain a lot of useful theming guidance, not only info on how to use FlexColorScheme package and its API, see https://docs.flexcolorscheme.com/

The ColorScheme in Material3 is quite a complex topic. It is a good idea to study it further in the Material 3 guide https://m3.material.io/styles/color/the-color-system/key-colors-tones

bksubhuti commented 11 months ago

I was able to manually change the appbar color .. in the appbar background color property. But I was not able to use some of the pastel pinks that come with my theme.. I didn't know which one to use.. but tried more or less all of them. I could get highlightcolor to work.

        appBar: Mobile.isPhone(context)
            ? AppBar(
                backgroundColor: Theme.of(context).highlightColor,
                title: Row(

but trying to get that pastel pink was not successful.. i tried using the themes and colors but got the same canvas color

backgroundColor: Theme.of(context).bottomAppBarTheme.color backgroundColor: Theme.of(context).floatingActionButtonTheme.backgroundColor etc I was unable to get that color based on the theme. I'll look into the docs you said. There are not many places where the appbar is used actually. But I'd like to know why I'm still getting the canvas color when these items are sure to be used in the buttons. and bottom app bar. I like the pastel stuff.. but I want a slight color on the app bar.

I appreciate your response.. I'll play a little more tomorrow. We are quite busy with studying for final exams. but I took a break to try this theme thing. The themes were easy to change to material 3.

bksubhuti commented 11 months ago

I jumped on the playground.. but it is a little complex. I looked at the app bar.. and it seemed to change color to the pastel version of the primary color. But that was only in the playground.. by default (in the theme without doing anything), I only get white for the appbar.

bksubhuti commented 11 months ago

I think the easiest thing to do .. would be to just keep everything standard with the theme and change the app bars to a matching pastel version of the primary.. but finding that pastel of the theme is not working for me.

bksubhuti commented 11 months ago

also same with almost anything I choose..

AppBar(
                backgroundColor: Theme.of(context).cardColor,
                title: Row(

image

bksubhuti commented 11 months ago

Through some trial and error.. I was able to find out that below worked. backgroundColor: Theme.of(context).primaryColorLight, I should probably just have less of a choice and more custom themes.. I have always wanted to Make burmese burgandy Siam orange Forest Brown Thai tan Sayalay (nun) pink Mahayana blue etc. to be fun.. I think I can do this now. I'll keep you posted. Then I assume, that I can just have the backgroundcolor of the appbar as NULL and let the theme do the work.

rydmike commented 11 months ago

What you are doing earlier above:

AppBar(
  backgroundColor: Theme.of(context).cardColor,
  title: Row(

is not theming, what you are doing above is trying to assign colors from ThemeData to an AppBar widget's background color.

You can certainly do that, but it is not theming the application and its components and it will not change the default color of all AppBar:s in your app to the specified color, only for the given AppBar, of course if that is the intent, then that is fine too of course.

Consider theming the AppBar What I showed you above earlier was how to set the default color for all AppBars in your app using ThemeData. If you want to have a consistent theme depending color in your application on all AppBars in your app, then theme the AppBar as I showed earlier. I recommend the newer API where you can select any of the ColorScheme colors as its color. In Material2 it was always primary by default, so use that if you still want that in Material3.


Another issue with your color assignments to the AppBar above is that unless you have defined color values for the component themes in ThemeData, they will all be null by default, this is just how Flutter works when using Material 2 and 3.

So for example:

backgroundColor: Theme.of(context).bottomAppBarTheme.color;

or

backgroundColor: Theme.of(context).floatingActionButtonTheme.backgroundColor; 

Unless your app has specified colors for those component theme colors in ThemeData, they will be null and not have any color value, so the color of the AppBar will not change. (Based on waht I saw from your theme setup you had not specified any custom theme colors for bottomAppBarTheme.color or floatingActionButtonTheme.backgroundColor, so those color value are null).

Depending on how you have made your ThemeData object with FlexColorScheme, certain component theme colors will indeed have color values, but they will not if you have kept them at defaults. At default values they will be null, and the color they get depends on the colors in the ColorScheme in your ThemeData.

Different Material widgets use different colors for different parts of the widget in question from the ColorScheme (Theme.of(context).colorScheme). The default color mappings from the ColorScheme follow the Material2 or Material3 design specifications, depending on which mode you use. With component themes you can change these mappings to other another ColorScheme color than the default one, or you can even give it a completely custom color value. Although FlexColorScheme on purpose restricts you to your theme's active ColorScheme colors.

To design a theme, you typically start with defining a ColorScheme. FlexColorScheme includes many tools to make defining a complete color scheme easier. It is especially tricky and demanding in Material3 mode that uses a lot of color that should have certain relations to each other and meet good contrast criteria too. Due to the demanding nature of making a Material3 ColorScheme using key color(s) seed generated ColorScheme is recommended. You can include the seed colors as color in your resulting ColorScheme if you want to, but default the exact seed colors do not typically end up in the produced ColorScheme, this is just how the M3 color algorithms work. With FlexColorScheme you can however lock the seed colors in so you can get them as your actual primary, secondary and tertiary colors. With Flutter's vanilla ColorScheme.fromSeed you can only use one seed color, the primary. FlexColorScheme allows you to use own seed colors for all three main colors.

Using your active theme colors

If you want to use the colors that your theme has defined, you should use them from Theme.of(context).colorScheme and then whichever of all the 30 ColorScheme colors you want to use from your theme.

Seed generated ColorScheme

To get beautiful ColorScheme using one of the seed strategies is recommended, because defining them all by hand is very tedious. FlexColorScheme will define all the ColorScheme values from the few input defaults as well (also when using the colors API) using its own legacy color aglorithms for them. However, the results are a bit different and better when you using the newer Material-3 color computation algos and my own additions to them to make them even more powerful and flexible.

Here is an example.

theme: FlexThemeData.light(
  // This with predefined `scheme` color, but works with custom `colors` API too. As a 3rd
  // option FlexColorScheme can also accept a full predefined `ColorScheme` as input via
  // its `colorScheme` property.
  scheme: FlexScheme.barossa,
  // This will make your app bars primary colored in both M2 and M3 mode.
  appBarStyle: FlexAppBarStyle.primary,  
  // Enable seed generated color scheme, this also works if you defined your colors
  // with the `colors` property instead of `scheme`.
  keyColors: const FlexKeyColors(
    // Used `scheme` or `colors`, primary color is always used as key color to seed
    // generate the `ColorScheme` below we also use secondary and tertiary colors as
    // input to the seed generation.
    useSecondary: true,
    useTertiary: true,
    // Keep the primary, secondary and tertiary as defined in scheme/colors, but 
    // use them as key seeds for each palette. This is only a good idea if the
    // used colors are designed to be used for the active theme mode light or dark.
    keepPrimary: true,
    keepSecondary: true,
    keepTertiary: true,
  ),
  // This defines the strategy of the used M3 color scheme seeding algorithm.
  // It impact how colorful, bright, pastel-like or matte the produced colors are
  // It also controls how M3 surface tint is made and which tonal palette tone
  // is mapped to which `ColorScheme` color. It comes with a large number of premade
  // configs, feel free to try them, but you can also make your own setups with the API.
  //
  // Seed generated color schemes includes their own M3 take on surface tint and blends. If
  // you also use `surfaceMode` and `blendLevel` they are added on top of what the seed 
  // generated M3 `ColorScheme` already added and it might become a bit too much.
  // If so, reduce the `blendLevel` value, if set to `0` you get the result as produced 
  // by the seed generation. Different M3 tone strategies have different surface tint, like
  // using more or less `blendLevel`.
  tones: FlexTones.candyPop(Brightness.light),
  useMaterial3: true,
),

Well anyway, I guess that is enough for now. No worries, I'll keep providing guidance until it clicks. One next step would be to show you some examples using your code. If it is still open source I can certainly do that. 😄 🙏🏻

bksubhuti commented 11 months ago

okay.. I understand a little more. I wanted to play with it and see how it looked "hardcoding it to the app bar". I plan on making custom themes like you showed in an example. I'll let you know when that happens. At least I understand what it looks like and can go from there.

I think early on.. when we first worked on this.. we didn't have that "flex" .. and that is why you made coloredText for me.
I'll look into the custom themes and maybe even faking a material2 as you said .
I'm not so smart.. but I think I can make it work as you say. The flex themes have been looking good and seeing people customize their app with the provided color themes gives me much joy because they they make the app "their own" when they change the default colors. So many merit to share with you on this application. I'll try tomorrow and then close the issue.

rydmike commented 11 months ago

You can hard code the color into the example AppBar by giving it e.g. these colors:

backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.surface, // or alt try `onPrimary`.

It is not themed globally then, but the AppBar in question will depend on those theme colors and will change with the theme light/dark and alternative user selectable theme options you might be offering, as those themes colorScheme changes. So from that point of view, it will use app theme colors, but it will not be themed to by default used those colors. Which I recommend to do, if you always want a certain given same style on all AppBar:s in the app.

If some or one AppBar needs to be different from the global desired/designed theme, then the above will still work as an override for that specific AppBar.


Themes Playground

https://rydmike.com/flexcolorscheme/themesplayground-latest/

You can put your custom colors into the Themes Playground too. You don't have to, but you can if you want see them there and experiment with them. Then you can configure and style everything else too the way you want it to look visually in the Playground.

If set the view to show the code on right side, and select a panel where you modify some aspects, you can observe what code it adds/changes for each operation, a nice way to learn the API, if so desired.

Themes Playground will generate the needed theme code, when you are done, you can copy-paste that code and only use the parts are new/different from your current FCS theme setup.

A simple way to learn more about using Themes Playground to configure FlexColorScheme API is to study recent Tweet thread guides that you can easily find here: https://docs.flexcolorscheme.com/tweets

Starting e.g. with version 7.0 guide, click on the embedded tweet link: https://docs.flexcolorscheme.com/tweets#version-7 (Version 5 and 6.1 tweet threads also contain still valid and useful principle and background information, but the app looked a bit different back then).

And version 7.2 https://docs.flexcolorscheme.com/tweets#version-72

There are also some guides, like understanding ColorScheme https://docs.flexcolorscheme.com/tweets#colorscheme-guide

A long theme story examples, with videos: https://docs.flexcolorscheme.com/tweets#a-theme-story

A platform agnostic theme example (screenshots): https://docs.flexcolorscheme.com/tweets#platform-agnostic-theme

bksubhuti commented 11 months ago

yes.. our code is FOSS except where data liimits. https://github.com/bksubhuti/tipitaka-pali-reader Some things are broken though. I'm not sure if it will compile and need a .env file in the root for firebase.
FIREBASE_API_KEY= There is also a db that needs to be downloaded listed in the readme file. then run split bash. But that can be removed and remove the sign in code. Perhaps you know how to read the flex code anyway without building.

I'd like to have some custom theme colors (especially the fun monk and nun names) and use the nonstandard material 3 appbar with a hybrid of appbar but it matching the pastel stuff. like this Theme.of(context).primaryColorLight, or the same as the floating action button. Something that sort of matches. However, I have put this on the shelf for the next 16 days because of big exams coming up.
Please keep this open.

We have a flexdata file in our data folder. I'm not sure how it works.
I'll have to look at this after oct 28th. I thought it would be quicker.. but not for my level.

bksubhuti commented 11 months ago

okay.. i don't think i'll be able to sleep until this is finished.. haha.. So where do I put the code to make modify the theme that I think I can make? https://github.com/bksubhuti/tipitaka-pali-reader/blob/master/lib/data/flex_theme_data.dart

One of the developers seems to have made a theme for orange 2 (or maybe it is yours..?). There is another toledo purple. I guess if you give me one theme that has a a color and a lighter version for the appbar, then I can duplicate it.

But if I make the appbar color red in the theme.. it does not show up.. class MyThemes { static const orange2Name = 'Orange 2'; static const FlexSchemeColor myScheme1Dark = FlexSchemeColor( primary: Color(0xFF9E7389), primaryContainer: Color(0xFF775C69), secondary: Color(0xFF738F81), secondaryContainer: Color(0xFF5C7267), // Again we use same secondaryVariant color as optional custom app bar color. appBarColor: Color(0xFF5C7267), );

static const FlexSchemeColor myScheme1Light = FlexSchemeColor( primary: Color(0xFF4E0028), primaryContainer: Color(0xFF320019), secondary: Color(0xFF003419), secondaryContainer: Color(0xFF002411), // The built in schemes use their secondary variant color as their // custom app bar color, it could of course be any color, but for consistency // we will do the same in this custom FlexSchemeColor. appBarColor: Colors.red, ); }

I don't understand much of this file which is located here. it seems like there are many steps to this.

bksubhuti commented 11 months ago

I created more themes with my names.. but I still don't understand the subtheme way to make an appbar appear. I see there is a playground output code.. section.. this is far more complex than I need. But.. I want to set it for each custom theme.. not globally. I'll fix the colors later.. I was just playing to make names.

The Theme change notifier code is here. I'd also like to make a switch for useMaterial3 as well.. based off of my hacky Prefs.useMaterial3 sort of global variable on user prefs.

//returns // flexschemedata
  get darkTheme => FlexColorScheme.dark(
        // As scheme colors we use the one from our list
        // pointed to by the current themeIndex.
        colors: myFlexSchemes[Prefs.themeIndex].dark,
        // Medium strength surface branding used in this example.
        surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
        visualDensity: FlexColorScheme.comfortablePlatformDensity,
        textTheme: _textTheme,
        useMaterial3: true,
      ).toTheme;

  ThemeData get themeData =>
      //ThemeData get themeData=>  myFlexSchemes[Prefs.themeIndex].light().toTheme();
      FlexColorScheme.light(
        // As scheme colors we use the one from our list
        // pointed to by the current themeIndex.
        useMaterial3: true,
        colors: myFlexSchemes[Prefs.themeIndex].light,
        // Medium strength surface branding used in this example.
        surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
        visualDensity: FlexColorScheme.comfortablePlatformDensity,
        textTheme: _textTheme,
      ).toTheme;
import 'package:flutter/material.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart';

FlexSchemeColor myFlexColorLight = FlexSchemeColor.from(
  primary: Colors.brown,
);

/*
const FlexSchemeColor myScheme1Light = FlexSchemeColor(
  primary: Color(0xFF4E0028),
  primaryVariant: Color(0xFF320019),
  secondary: Color(0xFF003419),
  secondaryVariant: Color(0xFF002411),
  // The built in schemes use their secondary variant color as their
  // custom app bar color, it could of course be any color, but for consistency
  // we will do the same in this custom FlexSchemeColor.
  appBarColor: Color(0xFF002411),
);

const FlexSchemeColor myScheme1Dark = FlexSchemeColor(
  primary: Color(0xFF9E7389),
  primaryVariant: Color(0xFF775C69),
  secondary: Color(0xFF738F81),
  secondaryVariant: Color(0xFF5C7267),
  // Again we use same secondaryVariant color as optional custom app bar color.
  appBarColor: Color(0xFF5C7267),
);

*/

class MyThemes {
  static const orange2Name = 'Orange 2';
  static const FlexSchemeColor myScheme1Dark = FlexSchemeColor(
    primary: Color(0xFF9E7389),
    primaryContainer: Color(0xFF775C69),
    secondary: Color(0xFF738F81),
    secondaryContainer: Color(0xFF5C7267),
    // Again we use same secondaryVariant color as optional custom app bar color.
    appBarColor: Color(0xFF5C7267),
  );

  static const FlexSchemeColor myScheme1Light = FlexSchemeColor(
    primary: Color(0xFF4E0028),
    primaryContainer: Color(0xFF320019),
    secondary: Color(0xFF003419),
    secondaryContainer: Color(0xFF002411),
    // The built in schemes use their secondary variant color as their
    // custom app bar color, it could of course be any color, but for consistency
    // we will do the same in this custom FlexSchemeColor.
    appBarColor: Color(0xFF002411),
  );
}

// Create a custom flex scheme color for a light theme.
const FlexSchemeColor myScheme1Light = FlexSchemeColor(
  primary: Color(0xFF4E0028),
  primaryContainer: Color(0xFF320019),
  secondary: Color(0xFF003419),
  secondaryContainer: Color(0xFF002411),
  // The built in schemes use their secondary variant color as their
  // custom app bar color, it could of course be any color, but for consistency
  // we will do the same in this custom FlexSchemeColor.
  appBarColor: Color(0xFF002411),
);
// Create a corresponding custom flex scheme color for a dark theme.
const FlexSchemeColor myScheme1Dark = FlexSchemeColor(
  primary: Color(0xFF9E7389),
  primaryContainer: Color(0xFF775C69),
  secondary: Color(0xFF738F81),
  secondaryContainer: Color(0xFF5C7267),
  // Again we use same secondaryVariant color as optional custom app bar color.
  appBarColor: Color(0xFF5C7267),
);

// You can build a scheme the long way, by specifying all the required hand
// picked scheme colors, like above, or can also build schemes from a
// single primary color. With the [.from] factory, then the only required color
// is the primary color, the other colors will be computed. You can optionally
// also provide the primaryVariant, secondary and secondaryVariant colors with
// the factory, but any color that is not provided will always be computed for
// the full set of required colors in a FlexSchemeColor.

// In this example we create our 2nd scheme from just a primary color
// for the light and dark schemes. The custom app bar color will in this case
// also receive the same color value as the one that is computed for
// secondaryVariant color, this is the default with the [from] factory.
final FlexSchemeColor myScheme2Light =
    FlexSchemeColor.from(primary: const Color(0xFF4C4E06));
final FlexSchemeColor myScheme2Dark =
    FlexSchemeColor.from(primary: const Color(0xFF9D9E76));

// For our 3rd custom scheme we will define primary and secondary colors, but no
// variant colors, we will not make any dark scheme definitions either.
final FlexSchemeColor myScheme3Light = FlexSchemeColor.from(
  primary: const Color(0xFF993200),
  secondary: const Color(0xFF1B5C62),
);

// Create a list with all color schemes we will use, starting with all
// the built-in ones and then adding our custom ones at the end.
final List<FlexSchemeData> myFlexSchemes = <FlexSchemeData>[
  // Use the built in FlexColor schemes, but exclude the placeholder for custom
  // scheme, a selection that would typically be used to compose a theme
  // interactively in the app using a color picker, we won't be doing that in
  // this example.
  ...FlexColor.schemesList,
  // Then add our first custom FlexSchemeData to the list, we give it a name
  // and description too.
  const FlexSchemeData(
    name: 'Toledo purple',
    description: 'Purple theme, created from full custom defined color scheme.',
    // FlexSchemeData holds separate defined color schemes for light and
    // matching dark theme colors. Dark theme colors need to be much less
    // saturated than light theme. Using the same colors in light and dark
    // theme modes does not look nice.
    light: myScheme1Light,
    dark: myScheme1Dark,
  ),
  // Do the same for our second custom scheme.
  FlexSchemeData(
    name: 'Olive green',
    description:
        'Olive green theme, created from primary light and dark colors.',
    light: myScheme2Light,
    dark: myScheme2Dark,
  ),
  // We also do the same for our 3rd custom scheme, BUT we create its matching
  // dark colors, from the light FlexSchemeColor with the toDark method.
  FlexSchemeData(
    name: 'Oregon orange',
    description: 'Custom orange and blue theme, from only light scheme colors.',
    light: myScheme3Light,
    // We create the dark desaturated colors from the light scheme.
    dark: myScheme3Light.toDark(),
  ),
  const FlexSchemeData(
    name: MyThemes.orange2Name,
    description: FlexColor.mangoDescription,
    light: FlexSchemeColor(
      primary: FlexColor.mangoLightPrimary,
      primaryContainer: FlexColor.mangoLightPrimaryContainer,
      secondary: FlexColor.mangoLightSecondary,
      secondaryContainer: FlexColor.mangoLightSecondaryContainer,
      tertiary: FlexColor.mangoLightTertiary,
      tertiaryContainer: FlexColor.mangoLightTertiaryContainer,
      appBarColor: FlexColor.mangoLightTertiary,
      error: FlexColor.materialLightError,
      swapOnMaterial3: true,
    ),
    dark: FlexSchemeColor(
      primary: FlexColor.mangoDarkPrimary,
      primaryContainer: FlexColor.mangoDarkPrimaryContainer,
      secondary: FlexColor.mangoDarkSecondary,
      secondaryContainer: FlexColor.mangoDarkSecondaryContainer,
      tertiary: FlexColor.mangoDarkTertiary,
      tertiaryContainer: FlexColor.mangoDarkTertiaryContainer,
      appBarColor: FlexColor.mangoDarkTertiary,
      error: FlexColor.materialDarkError,
      swapOnMaterial3: true,
    ),
  ),
  const FlexSchemeData(
    name: 'Mahayana blue',
    description: 'Mahayana Blue Color grey blue',
    light: FlexSchemeColor(
      primary: Color(0xFF00296B),
      primaryContainer: Color(0xFFA0C2ED),
      secondary: Color(0xFFD26900),
      secondaryContainer: Color(0xFFFFD270),
      tertiary: Color(0xFF5C5C95),
      tertiaryContainer: Color(0xFFC8DBF8),
    ),
    dark: FlexSchemeColor(
      primary: Color(0xFFB1CFF5),
      primaryContainer: Color(0xFF3873BA),
      secondary: Color(0xFFFFD270),
      secondaryContainer: Color(0xFFD26900),
      tertiary: Color(0xFFC9CBFC),
      tertiaryContainer: Color(0xFF535393),
    ),
  ),
  const FlexSchemeData(
    name: 'Pa-Auk Burgundy',
    description: 'Paauka Color Burgundy',
    light: FlexSchemeColor(
      primary: Color.fromARGB(255, 61, 10, 41),
      secondary: Color(0xFFD26900),
      swapOnMaterial3: true,
      appBarColor: FlexColor.mangoDarkTertiary,
    ),
    dark: FlexSchemeColor(
      primary: Color.fromARGB(255, 61, 10, 41),
      secondary: Color(0xFFD26900),
      swapOnMaterial3: true,
      appBarColor: FlexColor.mangoDarkTertiary,
    ),
  ),
  const FlexSchemeData(
    name: 'Sayalay Pink',
    description: 'Pink Color of Nun',
    light: FlexSchemeColor(
      primary: Color.fromARGB(255, 209, 158, 190),
      secondary: Color.fromARGB(255, 72, 49, 69),
    ),
    dark: FlexSchemeColor(
      primary: Color.fromARGB(255, 209, 158, 190),
      secondary: Color.fromARGB(255, 72, 49, 69),
    ),
  ),
];
rydmike commented 11 months ago

Yes FlexColorScheme (FCS) contains many different APIs to adjust things, it can certainly be confusing. But no worries, lets look at what seems to be relevant for your use case.

Since you are using the colors API, and a list of them, we have good option via it. This is btw a very good and simple way to define key custom colors and color theme options that users can choose from, nicely done! 😄

So let's take a look how to develop it a bit. You have this:

FlexColorScheme.light(
  // As scheme colors we use the one from our list
  // pointed to by the current themeIndex.
  colors: myFlexSchemes[Prefs.themeIndex].light,
  // Medium strength surface branding used in this example.
  surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
  visualDensity: FlexColorScheme.comfortablePlatformDensity,
  textTheme: _textTheme,
  useMaterial3: true,
).toTheme;

And since I see that a lot of your colors definitions contain custom appBarColor values, then to use that as your active AppBar color, all you need to do is to tell FlexColorScheme to use that custom color for the AppBarTheme it will make. This is done with the appBarStyle property.

FlexColorScheme.light(
  // As scheme colors we use the one from our list
  // pointed to by the current themeIndex.
  colors: myFlexSchemes[Prefs.themeIndex].light,
  // Use the custom color for app bar define in `FlexSchemeData.appBarColor` as
  // themed color of the AppBar.
  appBarStyle: FlexAppBarStyle.custom,
  // Medium strength surface branding used in this example.
  surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
  visualDensity: FlexColorScheme.comfortablePlatformDensity,
  textTheme: _textTheme,
  useMaterial3: true,
).toTheme;

The appBarStyle enum is intended to work as quick toggle between a few popular options. It also offers the possibility to make it an option that is easy to offer as a user configurable selection as well, like it the Theme Playground. Or to just select your preferred fixed selection.

Screenshot 2023-10-14 at 16 17 29

If you have not set the appBarStyle value to anything, the Material mode defaults are used. In Material 2 that means AppBar will be Theme.of(context).colorScheme.primary colored in light mode and M2 default surface color (#121212) in dark mode. In Material 3 mode the AppBar color will become Theme.of(context).colorScheme.surface colored.

If the colors property in FlexColorScheme or FlexThemeData uses a FlexSchemeColor that does not define a color for appBarColor, then it will be equal to the FlexSchemeColor.tertiary color, and if FlexSchemeColor did not define a FlexSchemeColor.tertiary color, a color based on FlexSchemeColor.secondary is used, and if it is not defined a color based on FlexSchemeColor.primary.

Always using and defining an appBarColor in FlexSchemeColor for both light and dark themes, in the colors property in FlexColorScheme or FlexThemeData, and setting appBarStyle to FlexAppBarStyle.custom is a simple and good way of customizing the themed AppBar color to any desired color for both light and dark mode individually.

Optional more ThemeData looking API FlexThemeData

When I talk about FlexThemeData it is just an alternative newer API (already very old too) that makes e.g `FlexColorScheme.light(...).toTheme look a bit nicer and familiar to Flutter devs. You could replace the above with:

FlexThemeData.light(
  // As scheme colors we use the one from our list
  // pointed to by the current themeIndex.
  colors: myFlexSchemes[Prefs.themeIndex].light,
  // Use the custom color for the app bar defined in `FlexSchemeData.appBarColor` as
  // the themed color of the AppBar.
  appBarStyle: FlexAppBarStyle.custom,
  // Medium strength surface branding used in this example.
  surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
  visualDensity: FlexColorScheme.comfortablePlatformDensity,
  textTheme: _textTheme,
  useMaterial3: true,
);

To make it look more "Flutter" like.

Using Themes Playground

Above you are using surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,, but since you have not defined any blendLevel it is actually not doing anything, since blendLevel defaults to zero. So it is not really needed in the config.

Too see and understand what blend level does, you can use Themes Playground, to modify it and see what happens and find a setting you like by looking at the API code it makes.

You can copy or just enter a single property you like, to your theme setup, no need to go all in and copy/paste everything, you can just use it to experiment and find new styles you like and add them as needed. This is what I meant with using the Themes Playground to learn how to utilize FlexColorScheme better.

Here is an example with the blendLevel:

https://github.com/rydmike/flex_color_scheme/assets/39990307/94b96f60-79f5-429f-8f0a-bcab1022f50e

You can even offer it a user configurable option if you want to 😄

Using sub themes with FlexColorScheme

Using sub-themes with FlexColorScheme or FlexThemeData is needed to customize all the components (Flutter Material UI widget) individually. Things like their ColorScheme depending colors, their corner border radius, elevations and a number of other key design features. You can customize the look of you app extensively by using component themes.

FAB example

Say you like the FloatingActionButton to always be circular, like it was in M2 by default, you can do this in M3 or actually regardless of M2/M3 mode by giving it a custom style:

https://github.com/rydmike/flex_color_scheme/assets/39990307/ddc2ad8b-5c5a-43a5-afb8-ca9edb5c58b7

Text field example

Maybe you want to customize the input decorator on the TextField to use primary with opacity and more rounded corners, like it was when using FCS in M2 mode also in M3 mode? You can do that and many more adjustments to the text input style.

https://github.com/rydmike/flex_color_scheme/assets/39990307/a7e751fa-a60b-4a55-8992-80941e81de4d

Seeded Material3 ColorScheme

To get the most out of Material-3 styling, I do recommend using a ColorScheme generated and computed by the Material 3 color system tools. FlexColorScheme offers that out of the box, with a lot more configuration options and flexibility than vanilla Flutter theming and ColorScheme does.

If you do not enable it, FlexColorScheme will still in M3 mode make color schemes that are highly compatible with Material 3 color system, using your custom colors as input and computing suitable colors for ColorScheme colors based on them. This is done for colors that did not exist in Material2 ColorScheme. But you get much better M3 color system fidelity if you enable seeded ColorScheme. For example in light mode like this:

https://github.com/rydmike/flex_color_scheme/assets/39990307/c0fb44ab-9c0d-4bf1-88ef-9935b66d6311

So something like this for your example:

FlexThemeData.light(
  // As scheme colors we use the one from our list
  // pointed to by the current themeIndex.
  colors: myFlexSchemes[Prefs.themeIndex].light,
  // Use the custom color for the app bar defined in `FlexSchemeData.appBarColor` as
  // the themed color of the AppBar.
  appBarStyle: FlexAppBarStyle.custom,
  // Medium strength surface branding used in this example.
  surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
  blendLevel: 4,
  appBarStyle: FlexAppBarStyle.primary,
  subThemesData: const FlexSubThemesData(
    blendOnLevel: 10,
    inputDecoratorSchemeColor: SchemeColor.primary,
    inputDecoratorBackgroundAlpha: 16,
    inputDecoratorRadius: 12.0,
    fabUseShape: true,
    fabAlwaysCircular: true,
  ),
  keyColors: const FlexKeyColors(
    useSecondary: true,
    useTertiary: true,
    keepPrimary: true,
    keepSecondary: true,
    keepTertiary: true,
  ),
  visualDensity: FlexColorScheme.comfortablePlatformDensity,
  textTheme: _textTheme,
  useMaterial3: true,
);

In dark mode you could try just this:

FlexThemeData.dark(
  // As scheme colors we use the one from our list
  // pointed to by the current themeIndex.
  colors: myFlexSchemes[Prefs.themeIndex].dark,
  // Use the custom color for the app bar defined in `FlexSchemeData.appBarColor` as
  // the themed color of the AppBar.
  appBarStyle: FlexAppBarStyle.custom,
  // Medium strength surface branding used in this example.
  surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
  blendLevel: 10,
  appBarStyle: FlexAppBarStyle.primary,
  subThemesData: const FlexSubThemesData(
    blendOnLevel: 15,
    inputDecoratorSchemeColor: SchemeColor.primary,
    inputDecoratorBackgroundAlpha: 38,
    inputDecoratorRadius: 12.0,
    fabUseShape: true,
    fabAlwaysCircular: true,
  ),
  keyColors: const FlexKeyColors(
    useSecondary: true,
    useTertiary: true,
  ),
  visualDensity: FlexColorScheme.comfortablePlatformDensity,
  textTheme: _textTheme,
  useMaterial3: true,
);

Using a bit differently tuned blend levels and alpha in dark mode, and also removing:

    keepPrimary: true,
    keepSecondary: true,
    keepTertiary: true,

However if you in your colors have very good custom dark colors defined for primary, secondary and/or tertiary for all your offered color schemes, you can certainly use the keep option to get those color instead of the seed generated one for those particular colors.

You can also experiment and try different color scheme seed generation strategies with tones. If not defined, the Material3 default one is used, but FlexColorScheme offers many additional useful options.

Screenshot 2023-10-14 at 17 35 01

For example tones: FlexTones.ultraContrast(Brightness.light), can be used to make themes with more contrast, especially in dark mode. The seed generation will always use your colors as input, but the different seed generation option can change the mood of the color theme or be used as an accessibility feature.

You can even make your own custom FlexTones with the API.

Material 3

Personally I don't think it is good idea to offer a toggle between Material-2 (legacy) and Material-3 anymore. In next version of Flutter, Material-3 will be default when you create ThemeData, to opt out of Material-3, you will have to set useMaterial3: false explicitly.

Material-2 mode will also be deprecated, and when that happens, maybe a year after it is deprecated, Material-2 mode support will be removed from Flutter completely.

Material-3 theming in Flutter is however very powerful and offers a lot more customizing capabilities than Material-2 mode ever did. You can in fact make Material-3 to look like Material-2 by customizing the theme of all Widgets in Material-3 mode. This is in fact available as a pre-built theming example in Themes Playground among several others:

https://github.com/rydmike/flex_color_scheme/assets/39990307/4bc19ad7-402e-4e71-ba6e-f1851648b637

The premade design are just examples that one can study to see how it is done, or use as staring points for own design. 😄

bksubhuti commented 11 months ago

Wow.. I'm very impressed.. I'm starting to digest and understand the playground and the app data. and the FlexThemeData.light() Before, I was just cutting and pasting.. take note.. I made the appbar color red, so I would know it was working or not. Obviously an eyesore. Through your discussions. I think I need to do this globally according to our current code and the theme selector. Although I think I have plenty of time to do m2 switch and get away with it.. so that the users can feel comfortable, Your fake m2 will do the trick. Your embedded videos work really well for me. I have noticed that if I do end up with a appbar, which I can do, the colors for the writing and focus get out of wack and contrast to read is lost. I guess I had to get to this stage to understand that. Changing this and that to make it work will be too much trouble. Therefore.. through this conversation.. I think it is best to stay standard, and have an m2 switch (fakestyle), . I guess I either need to swap the switch with the subtheme or just swap out the whole light class with the prefs.them

So this code below works.. (The code output had scheme.. and I replaced with colors which worked). So all I need to do is return this, or the standard one based on the switch and my problem is solved. Then the users can double the theme choices. Your help was much appreciated.
This works as I would like. I also know how to have a mix version by making m3 with a subtheme with a mostly transparent appbar.

So.. I think you can close the issue.. the code below works for me after I make a switch.

 ThemeData get themeData {
    if (Prefs.useM3) {
      return FlexColorScheme.light(
        // As scheme colors we use the one from our list
        // pointed to by the current themeIndex.
        useMaterial3: true,
        colors: myFlexSchemes[Prefs.themeIndex].light,
        // Medium strength surface branding used in this example.
        surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
        visualDensity: FlexColorScheme.comfortablePlatformDensity,
        textTheme: _textTheme,
      ).toTheme;
    } else {
      return
          //ThemeData get themeData=>  myFlexSchemes[Prefs.themeIndex].light().toTheme();
          FlexThemeData.light(
        colors: myFlexSchemes[Prefs.themeIndex].light,
        appBarStyle: FlexAppBarStyle.primary,
        appBarElevation: 4.0,
        bottomAppBarElevation: 8.0,
        tabBarStyle: FlexTabBarStyle.forAppBar,
        subThemesData: const FlexSubThemesData(
          interactionEffects: false,
          tintedDisabledControls: false,
          blendOnColors: false,
          useTextTheme: true,
          useM2StyleDividerInM3: true,
          adaptiveRemoveElevationTint: FlexAdaptive.all(),
          adaptiveElevationShadowsBack: FlexAdaptive.all(),
          adaptiveAppBarScrollUnderOff: FlexAdaptive.all(),
          defaultRadius: 4.0,
          elevatedButtonSchemeColor: SchemeColor.onPrimary,
          elevatedButtonSecondarySchemeColor: SchemeColor.primary,
          inputDecoratorSchemeColor: SchemeColor.onSurface,
          inputDecoratorBackgroundAlpha: 13,
          inputDecoratorBorderSchemeColor: SchemeColor.primary,
          inputDecoratorUnfocusedBorderIsColored: false,
          fabUseShape: true,
          fabAlwaysCircular: true,
          chipSchemeColor: SchemeColor.primary,
          chipRadius: 20.0,
          popupMenuElevation: 8.0,
          alignedDropdown: true,
          tooltipRadius: 4,
          dialogElevation: 24.0,
          useInputDecoratorThemeInDialogs: true,
          datePickerHeaderBackgroundSchemeColor: SchemeColor.primary,
          snackBarBackgroundSchemeColor: SchemeColor.inverseSurface,
          appBarScrolledUnderElevation: 4.0,
          tabBarIndicatorSize: TabBarIndicatorSize.tab,
          tabBarIndicatorWeight: 2,
          tabBarIndicatorTopRadius: 0,
          tabBarDividerColor: Color(0x00000000),
          drawerElevation: 16.0,
          drawerWidth: 304.0,
          bottomSheetElevation: 10.0,
          bottomSheetModalElevation: 20.0,
          bottomNavigationBarSelectedLabelSchemeColor: SchemeColor.primary,
          bottomNavigationBarSelectedIconSchemeColor: SchemeColor.primary,
          bottomNavigationBarElevation: 8.0,
          menuElevation: 8.0,
          menuBarRadius: 0.0,
          menuBarElevation: 1.0,
          navigationBarSelectedLabelSchemeColor: SchemeColor.onSurface,
          navigationBarUnselectedLabelSchemeColor: SchemeColor.onSurface,
          navigationBarSelectedIconSchemeColor: SchemeColor.onSurface,
          navigationBarUnselectedIconSchemeColor: SchemeColor.onSurface,
          navigationBarIndicatorSchemeColor: SchemeColor.secondary,
          navigationBarBackgroundSchemeColor: SchemeColor.surfaceVariant,
          navigationBarElevation: 0.0,
          navigationRailSelectedLabelSchemeColor: SchemeColor.onSurface,
          navigationRailUnselectedLabelSchemeColor: SchemeColor.onSurface,
          navigationRailSelectedIconSchemeColor: SchemeColor.onSurface,
          navigationRailUnselectedIconSchemeColor: SchemeColor.onSurface,
          navigationRailIndicatorSchemeColor: SchemeColor.secondary,
        ),
        visualDensity: FlexColorScheme.comfortablePlatformDensity,
        useMaterial3: true,
        // To use the Playground font, add GoogleFonts package and uncomment
        // fontFamily: GoogleFonts.notoSans().fontFamily,
      );
    }
  }
bksubhuti commented 11 months ago

If you are in Sri Lanka or near it .. give a buzz.. my username is my google email. If you google our app you will find my website too. americanmonkDOTorg, I love your dedication for your theme and helping others. Your theme will be even more popular with this future m3 enforcement. We are a study monastery in elephant land and a hot climate. I have spent half my time in myanmar and Sri lanka if you need travel advice. We always have extra food.. you can stop by for lunch if I'm there or not. (but let me know first).

rydmike commented 11 months ago

Happy if you are learning more about theming and are now able to get the result you want. 😄 🙏🏻

You don't need to go all in on using the Material3 made Material2 style, just to get the AppBar color fixed to be as it was before, as shown in other examples. Of course to know how to make what you had before I would need to try it in M2 and M3 mode, but correct appBarStyle selection in light and dark mode should be able to fix to be same as before.

Basically setting appBarStyle to FlexAppBarStyle.primary in light mode and FlexAppBarStyle.surface in dark mode, should be what you had before, since you had not customized it. The appBarColor in FlexSchemeData does not matter if you never used appBarStyle set to FlexAppBarStyle.custom.

Also do note that "Material2" look alike style made by FCS built in sample, is not the same as as the FCS Material2 defaults you had before. The example is more of default standard Material2 style. The old FCS default for Material2 contained a number of opinionated own custom defaults, so you will see a lot of differences if you use that.

It is possible to configure Material3 mode to be like previous FCS M2 defaults, but there is no preconfigured example for it. The examples I added above should actually already be closer to what you had before than the full "native" old Material2 default design. What you might need to add is custom FAB color, since it defaults to primaryContainer in M3 but to secondary in M2. Many small detail changes like that. Buttons also have new default color mappings in M3. But as said you can change all of this to be whatever you want, just use Themes Playground to observer the difference, and copy just the single config line to get what you want, no need to learn the API when doing that.

By the way, I'm not sure what you meant with:

"I have noticed that if I do end up with a AppBar, which I can do, the colors for the writing and focus get out of wack and contrast to read is lost."

It is not something that I have observed when using FlexColorScheme. I have not tried building your app, so I have not looked at its details recently.

rydmike commented 11 months ago

I'm going to close this issue, and move it to be preserved just as discussion in the FAQ section, where others can find it and learn from it too. We can continue the discussion there! 😄