rydmike / flex_color_picker

A highly customizable Flutter color picker.
BSD 3-Clause "New" or "Revised" License
198 stars 41 forks source link

How add greyscale in custon tonal palette? #49

Closed Gilianp closed 2 years ago

Gilianp commented 2 years ago

I'm creating a custom palette based on primary colors. For this I create use "ColorTools.primaryColorNames" and then I would like to add the color Black, and then when I click on that color, grayscale (black and white) is displayed in the tonal palette. Is possible? Thanks for the amazing lib

rydmike commented 2 years ago

Hi @Gilianp, thanks for the question.

To the Material 3 tonal palette you cannot really add a custom palette, but I will probably add the capability to tune the parameters it uses to compute the palette in a future update, and even return the entire palette.

The algorithm can compute black to white palette too, if you give it "zero" as chroma, so then it could be used, but you would have to have it in new picker where you can set its min chroma level to zero to get a black and white palette with greys inbetween.

In current versions its min chroma level is 48, like it is for primary color in the Material 3 color algo. So even if you give an almost black or white value, it always finds the dominant chroma in it and creates a colored palette from black to white. If it is pure white, it becomes blue palette and pure black become a red palette. Regardless of what color / chroma it has, it always starts with black and ends with white. But if one gives the algo "zero" as chroma it will create black to white palette with nice nuances in between. Might be nice feature to add a Tonal palette picker that uses prefined params too, then one could define this as predefined tonal palette among other. Hmm cool idea, thanks! :D


However, if all you want is a white to black palette with greys in between, what you can do right now, is to use custom MaterialColor for it that you add to the custom "colors" picker.

You could define this MaterialColor color e.g. like so:

  // Add a custom white to black grey scale.
  static const MaterialColor whiteToBlack = MaterialColor(
    0xFF7C7D80, // Set the 500 index value here. Does not have to be it, but that is the norm.
    <int, Color>{
      50: Color(0xFFFFFFFF),
      100: Color(0xFFE1E2E4),
      200: Color(0xFFC7C8CA),
      300: Color(0xFFACADB0),
      400: Color(0xFF949599),
      500: Color(0xFF7C7D80),
      600: Color(0xFF646567),
      700: Color(0xFF48484A),
      800: Color(0xFF212121),
      900: Color(0xFF000000),
    },
  );

Obviously the color values can be whatever above, and you can start with black for index 50 too and end with white, but usually the order is from lighter to darker shade in Material Color, where the new M3 Tonal Palette is the other way around.

Then add this custom MaterialColor to a map Map<ColorSwatch<Object>, String> with all your other custom colors you want in your picker, like here where I'm adding it last in the ColorSwatch, name map of colors. The MaterialColor is a sub class of ColorSwatch so we can do this:

  // A custom color swatch, to name map, for the above custom colors.
  static Map<ColorSwatch<Object>, String> get colorsNameMap =>
      <ColorSwatch<Object>, String>{
        ColorTools.createPrimarySwatch(guideNewPrimary): 'Guide Purple',
        ColorTools.createPrimarySwatch(guideNewPrimaryVariant):
            'Guide Purple Variant',
        ColorTools.createAccentSwatch(guideNewSecondary): 'Guide Teal',
        ColorTools.createAccentSwatch(guideNewSecondaryVariant):
            'Guide Teal Variant',
        ColorTools.createPrimarySwatch(guideNewError): 'Guide Error',
        ColorTools.createPrimarySwatch(guideNewErrorDark): 'Guide Error Dark',
        ColorTools.createPrimarySwatch(blueBlues): 'Blue blues',
        ColorTools.createPrimarySwatch(clearBlue): 'Clear blue',
        ColorTools.createPrimarySwatch(darkPink): 'Dark pink',
        ColorTools.createPrimarySwatch(redWine): 'Red wine',
        ColorTools.createPrimarySwatch(grassGreen): 'Grass green',
        ColorTools.createPrimarySwatch(moneyGreen): 'Money green',
        ColorTools.createPrimarySwatch(mandarinOrange): 'Mandarin orange',
        ColorTools.createPrimarySwatch(brightOrange): 'Bright orange',
        ColorTools.createPrimarySwatch(brightGreen): 'Bright green',
        ColorTools.createPrimarySwatch(blueJean): 'Washed jean blue',
        ColorTools.createPrimarySwatch(deepBlueSea): 'Deep blue sea',
        whiteToBlack: 'White to black',
      };
}

The above code snippet is from the repo web demo picker. Using the lazy/easy way to make swatch that I used for the other colors via ColorTools.createPrimarySwatch(Color(0xFF7C7D80)) would not have worked (which I think you noticed too) since it does not start at white or end in black, but defining a custom MaterialColor like this manually works just fine. It is not necessary to use ColorTools.createPrimarySwatch helper to make the ColorSwatch or in this case its subclass version MaterialColor

Then in the picker you would pass this map to custom colors to customColorSwatchesAndNames map and of course make sure you have enabled the custom picker via pickersEnabled and you can also change the label for the picker selection with pickerTypeLabels and call it something else, if you only have this one "grey scale" material color in it, you could even call it "Greyscale".

SIDENOTE: I have not tried this, but based on how the picker is implemented, it might work. So if you want to go wild and make a greyscale color with e.g 20 shades from white to black, you could extend ColorSwatch the way MaterialColor does and use that, call it eg class MaterialColor extends ColorSwatch<int> and use as many index as desired. Although I'm not 100% sure it works, I might have some special handling in it that limits it to MaterialColor and MaterialAccentColor sub classes of ColorSwatch. I would have to check, in theory it should work, but it depends, now I even got curious to try it, come to think of it, it might not work, I think it needs to know the indexes and checks what type of sub class to ColorSwatch class it is, to "know" the index that it needs in some places in the picker.

I added the above changes to the repo web demo, you can find it here: https://github.com/rydmike/flex_color_picker/commit/b0c8f188fb5888bce2197c56f239ba9037af07ff

I did not yet build a new version of the web demo with this demo color added, but it will be in next build I make. You can build it if you want to try it, but below is what it looks like. It shows up among the other custom colors I had in there before:

image


And you can select the palette colors from white, to last one being black.

image


As said you can defines the shades or colors in the palette as you prefer, does not have to be the values I used above.


If you have the Material name ON you will se its Material name as "White to black" for indexes not having the pure black or white value, but for black and white you get them as names. Also the name that color picks up funky names for the greyscale colors too:

image

image

image

image


Anyway, hope this helps :D

rydmike commented 2 years ago

@Gilianp did the above help and answer your question? Let me know. I'm going to close the issue as answered if I don't hear back from you in a few days 💙