Flutter color animation produces unwanted flashing

Issue

I want to animate from this white color with slight opacity to a black color with very high opacity.

Colors are

  • Color(0xB1FFFFFF) – White
  • Color(0x0B000000) – Black

This will produce an animation with a "flash". However, this should not happen.

What am I doing wrong? When doing the same animation with css, it does not "flash".

This is how it looks when using css and how I would expect it:

animation

The jump to white is not important, it’s just the animation restarting.

import 'dart:math';

import 'package:flutter/material.dart';

void main() => runApp(const AnimatedContainerApp());

class AnimatedContainerApp extends StatefulWidget {
  const AnimatedContainerApp({Key? key}) : super(key: key);

  @override
  _AnimatedContainerAppState createState() => _AnimatedContainerAppState();
}

class _AnimatedContainerAppState extends State<AnimatedContainerApp> {
  double _width = 50;
  double _height = 50;
  Color _color = Color(0xB1FFFFFF);
  BorderRadiusGeometry _borderRadius = BorderRadius.circular(8);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('AnimatedContainer Demo'),
        ),
        body: Center(
          child: AnimatedContainer(
            width: _width,
            height: _height,
            decoration: BoxDecoration(
              color: _color,
              borderRadius: _borderRadius,
            ),
            duration: const Duration(seconds: 1),
            curve: Curves.fastOutSlowIn,
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              _color = Color(0x0B000000);
            });
          },
          child: const Icon(Icons.play_arrow),
        ),
      ),
    );
  }
}

Solution

I now understand why this "issue" exists.
Since both colors vary a lot both in opacity and color, a basic interpolation by time over the rgba values produces this behavior.
Whilst the alpha is being interpolated, the color is so too, and this creates a temporary darker color in between.

Dart interpolates colors by mapping the difference in colors to the time in the rgba spectrum.

a + (b - a) * t

This article describes very good what happens and other possible solutions for interpolating colors.

Also using HSL instead of rgba might also solve the issue. However, converting the color to HSL every time is not near as performant as flat rgba interpolation. Dart is all about performance, so this might be why they went for this very basic approach.

My personal solution to the problem was a very basic one though. I asked the designer to bring the colors closer together 🙂

Answered By – Inf0rmatix

Answer Checked By – Candace Johnson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *