31

I want to change text (and Icon) colors based on the background image for visibility.

I've tried: Using palette_generator package, to check the Dominant Color of the background Image and useWhiteForgroundForColor function (returns a bool) from flutter_statusbarcolor package to select black or white color for the my text (and Icon) colors.

The Problem: Sometimes dominant color turns out null. In my tests, this happens with black and white colors and I don't know of any ways to find out which one.

Future<bool> useWhiteTextColor(String imageUrl) async {
  PaletteGenerator paletteGenerator =
      await PaletteGenerator.fromImageProvider(
    NetworkImage(imageUrl),

    // Images are square
    size: Size(300, 300),

    // I want the dominant color of the top left section of the image
    region: Offset.zero & Size(40, 40),
  );

  Color dominantColor = paletteGenerator.dominantColor?.color;

  // Here's the problem 
  // Sometimes dominantColor returns null
  // With black and white background colors in my tests
  if (dominantColor == null) print('Dominant Color null');

  return useWhiteForeground(dominantColor);
}

I found other methods for other languages, but I don't know a way to implement the same method in dart.

Additional note: My actual code includes some additional complications. I am using a SliverAppBar and here I want to determine the title and icons colors for when the flexibleSpace is expanded. I change their colors when collapsed with the help of the community based on this.

dshukertjr
  • 15,244
  • 11
  • 57
  • 94
Sina Seirafi
  • 2,073
  • 3
  • 15
  • 16

6 Answers6

47

the color class already has a method to calculate luminance, called computeLuminance()

Color textColor = color.computeLuminance() > 0.5 ? Colors.black : Colors.white;
Leo
  • 696
  • 6
  • 3
9

i use the below method to find out which one to be used (either black or white).

Color getTextColor(Color color) {
int d = 0;

// Counting the perceptive luminance - human eye favors green color...
double luminance =
    (0.299 * color.red + 0.587 * color.green + 0.114 * color.blue) / 255;

if (luminance > 0.5)
  d = 0; // bright colors - black font
else
  d = 255; // dark colors - white font

return Color.fromARGB(color.alpha, d, d, d);   }
Star Lut
  • 416
  • 6
  • 11
4

There are Two ways of getting Text Color based upon the BG Color of Card or Button or Tags.

First One is :

Color txColor = color.computeLuminance() < 0.5 ? Colors.white : Colors.black;

The Second is using Theme , Where user may have dark theme or light theme of device.

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

class ColorEstimationPage extends StatelessWidget {
  Color _randomBackgroundColor() {
    List<Color> colors = [Colors.red, Colors.green, Colors.amber, Colors.black];

    return colors[Random().nextInt(colors.length)];
  }
   /// With this you can get the Color either black or white
  Color _textColorForBackground(Color backgroundColor) {
    if (ThemeData.estimateBrightnessForColor(backgroundColor) ==
        Brightness.dark) {
      return Colors.white;
    }

    return Colors.black;
  }

  @override
  Widget build(BuildContext context) {
    Color bgColor = _randomBackgroundColor();
    return Scaffold(
      backgroundColor: bgColor,
      body: Center(
        child: Text(
          "I'm the correct text color!",
          style: TextStyle(color: _textColorForBackground(bgColor)),
        ),
      ),
    );
  }
}
2

You should create the palette generator like this

PaletteGenerator paletteGenerator =
  await PaletteGenerator.fromImageProvider(
NetworkImage(imageUrl),

filters: [],
// Images are square
size: Size(300, 300),

// I want the dominant color of the top left section of the image
region: Offset.zero & Size(40, 40),
); 

notice the empty list in the filters parameter

bar
  • 176
  • 2
2

Colorful colors

If you have font/background colors that aren't only black and white, you should use some thing else:

 final colorDifference = newBackgroundColor.computeLuminance() -
        textColor.computeLuminance();
    if (colorDifference.abs() < 0.2) {
      textColor = textColor.computeLuminance() > 0.5
          ? Colors.black
          : Colors.white;
    }

With this, you will only change the font color if necessary (the luminance difference is so less that the colors don't really stand out).

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Paul
  • 1,349
  • 1
  • 14
  • 26
-1

For buttons you can use. this will auto change button color based on background

buttonTheme: ButtonThemeData(
   buttonColor: Colors.teal[500],
   textTheme: ButtonTextTheme.primary
)
aWebDeveloper
  • 36,687
  • 39
  • 170
  • 242