user3046679
user3046679

Reputation: 91

Animated container with gradient background color

How can I change the background color of a container from bottom to top? When I use gradients, I don't like the effect. I build a second container, but it's not dynamic.

class MyCustomContainer extends StatefulWidget {
  final Color backgroundColor;
  final Color progressColor;
  final double progress;
  final double size;

  const MyCustomContainer({
    Key key,
    this.backgroundColor = Colors.grey,
    this.progressColor = Colors.red,
    @required this.progress,
    @required this.size,
  }) : super(key: key);

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

class _MyCustomContainerState extends State<MyCustomContainer> {
  double _progress;

  @override
  void initState() {
    super.initState();
    _progress = widget.progress;
  }

  onPaint() {
    setState(() {
      if (_progress == 0) {
        _progress = 1;
      } else {
        _progress = 0;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SizedBox(
          height: widget.size,
          width: widget.size,
          child: Stack(
            children: [
              Container(
                color: widget.backgroundColor,
                child: Column(
                  children: [
                    Container(
                      height: widget.size * 0.3,
                      color: Colors.green,
                    ),
                    Container(
                      height: widget.size * 0.7,
                      color: Colors.red,
                    ),
                  ],
                ),
              ),
              Align(
                alignment: Alignment.bottomCenter,
                child: AnimatedContainer(
                  duration: Duration(milliseconds: 300),
                  curve: Curves.easeInOutExpo,
                  height: widget.size * _progress,
                  child: Column(children: [
                    Container(
                      height: widget.size * 0.3,
                      color: Colors.red,
                    ),
                    Container(
                      height: widget.size * 0.7,
                      color: Colors.green,
                    ),
                  ]),
                ),
              ),
              Text('asdas'),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => onPaint(),
        child: Icon(Icons.ac_unit),
      ),
    );
  }
}

I want that transition, over an over again changing the colors of the two containers. If the states changes, do the transition and in the next iteration, change colors and play again. This is the animation to emulate. Video animation

Any idea how?

Upvotes: 3

Views: 3010

Answers (1)

sonic
sonic

Reputation: 1431

There is something like ColorTween class ( https://api.flutter.dev/flutter/animation/ColorTween-class.html )

You can google some tutorial how to do that, there is plenty of it.

Update

In case that you want to hover one container with another and then in time reaviling it I would put both Containers into the Stack widget and set initial height of one of Containers to 0 and just animate height.

Update 2

To be able to control animation you should use AnimationController and you could forget about using AnimatedContainer.

As I experimented in the ways how to reset AnimatedContainer, there is some trick to do that. The key is to set callback onEnd and inside to change duration to 1 milisecond, restore _progress to initial value and setState , Before starting animation again you will need to set proper duration.

void initState() {
    super.initState();
    _progress = 0;
  }

  onPaint() {
    setState(() {
      dynamicDuration = Duration(milliseconds: 2000);
      if (_progress == 1) {
        _progress = 0;
      } else {
        _progress = 1;
      }
    });
  }
  
  void resetAnim(){
    
    setState((){
      dynamicDuration = Duration(milliseconds: 1);
      _progress = 0;
    });
    
  }

Update 3

to be able to loop it you would have to use async function to wait till restoration to point A has ended

  void resetAnim() async {
    
    setState((){
      dynamicDuration = Duration(milliseconds: 1);
      _progress = 0;
     
    });
    
     await new Future.delayed(const Duration(milliseconds : 50));
      
     
     setState(() {
      dynamicDuration = Duration(milliseconds: 2000);
      
        _progress = 1;
     
    });

It all looks kinda tricky/dirty so maybe it would be worth learning to use AnimationController and/or TweenAnimationBuilder

Upvotes: 1

Related Questions