34、Flutter之组件过度动画

Widget属性发生变化时会执行过渡动画的组件统称为”动画过渡组件“,而动画过渡组件最明显的一个特征就是它会在内部自管理AnimationController。我们知道,为了方便使用者可以自定义动画的曲线、执行时长、方向等,在前面介绍过的动画封装方法中,通常都需要使用者自己提供一个AnimationController对象来自定义这些属性值。但是,如此一来,使用者就必须得手动管理AnimationController,这又会增加使用的复杂性。因此,如果也能将AnimationController进行封装,则会大大提高动画组件的易用性。

自定义动画过渡组件


我们要实现一个AnimatedDecoratedBox,它可以在decoration属性发生变化时,从旧状态变成新状态的过程可以执行一个过渡动画。根据前面所学的知识,我们实现了一个AnimatedDecoratedBox1组件:

/// @Author wywinstonwy
/// @Date 2022/1/16 10:15 上午
/// @Description: 
import "package:flutter/material.dart";

class AnimatedDecoratedBox1 extends StatefulWidget {
  final BoxDecoration decoration;
  final Widget child;
  final Duration duration;
  final Curve ?curve;
  final Duration? reverseDuration;

  const AnimatedDecoratedBox1({
    required this.decoration,
    required this.child,
    required this.duration,
     this.curve,
      this.reverseDuration});


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

class _AnimatedDecoratedBox1State extends State<AnimatedDecoratedBox1> with SingleTickerProviderStateMixin{
  AnimationController get controller=>_controller;
  late AnimationController _controller;
  late Animation<double> _animation;
  late DecorationTween _tween;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _controller = AnimationController(
      duration: widget.duration,
      reverseDuration: widget.reverseDuration,
      vsync: this
    );

    _tween = DecorationTween(begin: widget.decoration);
    _updateCurve();
  }
  void _updateCurve(){
    _animation = CurvedAnimation(parent: _controller, curve: widget.curve!);
  }
  @override
  void didUpdateWidget(covariant AnimatedDecoratedBox1 oldWidget) {
    super.didUpdateWidget(oldWidget);
    if(widget.curve != oldWidget) _updateCurve();
    _controller.duration = widget.duration;
    _controller.reverseDuration = widget.reverseDuration;
    //正在执行过度动画
    if(widget.decoration !=(_tween.end??_tween.begin)){
      _tween
      ..begin =_tween.evaluate(_animation)
      ..end = widget.decoration;

      _controller
      ..value=0.0
      ..forward();
    }


  }
  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      builder: (BuildContext context, Widget? child) {
        return DecoratedBox(

            decoration: _tween.animate(_animation).value);
      },
      animation: _animation,
      child:widget.child,
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();

  }

}

下面我们来使用AnimatedDecoratedBox1来实现按钮点击后背景色从蓝色过渡到红色的效果:


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

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

class _MyExcessiveAnimationState extends State<MyExcessiveAnimation> {
  Color _decorationColor = Colors.blue;
  var duration = Duration(seconds: 1);
  // Curve curve = CurvedAnimation(parent: ) as Curve;
  // Tween doubleTween =  Tween<double>(begin: -200.0, end: 0.0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: getAppBar("组件过度动画"),
      body: Column(children: [
        ElevatedButton(onPressed: (){
          setState(() {
            _decorationColor = Colors.red;
          });
        }, child: const Text('测试')),
        Container(height: 44,
          width: 200,
          child: AnimatedDecoratedBox1(
          decoration: BoxDecoration(color: _decorationColor),
          child: ElevatedButton(onPressed: (){
            setState(() {
              _decorationColor = Colors.red;
            });
          },
              child: const Text('AnimatedDecoratedBox',
                style: TextStyle(color: Colors.black,fontSize: 14),
              )
          ),
          duration: duration,
          curve: Curves.linear,
        ),
        )

      ],)
      ,
    );
  }
}

 

点击后,按钮背景色会从蓝色向红色过渡,上图是过渡过程中的一帧,有点偏紫色,整个过渡动画结束后背景会变为红色。 

demo完整代码:flutter_demo: flutter组件测试学习demo

猜你喜欢

转载自blog.csdn.net/wywinstonwy/article/details/122519963