26

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
  • 10,828
  • 9
  • 47
  • 85
Sina Seirafi
  • 1,463
  • 2
  • 14
  • 14

5 Answers5

32

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

Color textColor = color.computeLuminance() > 0.5 ? Colors.black : Colors.white;
Leo
  • 536
  • 5
  • 2
7

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
  • 356
  • 5
  • 11
2

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)),
        ),
      ),
    );
  }
}
1

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
  • 166
  • 2
-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
  • 33,798
  • 37
  • 161
  • 232