Flutter学习笔记之-基础动画的基本使用

基础动画的概念和API认识

1、Animation动画的抽象类,能够实现对动画状态的监听和动画的监听(addStatusListener和addListener)。
2、AnimationController动画的管理类
3、CurvedAnimation管理动画的运动曲线
4、Tween自定义AnimationController中lowerBound和lowerBound值

动画案例实现

  • 基础动画

实现一个基本的动画(从小变大,再从大变小),并实现对动画状态的监听。

class _DemoWidgetState extends State<DemoWidget> with SingleTickerProviderStateMixin {

  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    // 创建动画
    _controller = AnimationController(
      duration: Duration(seconds: 1), vsync: this
    );
    // 设置动画的执行曲线为线性
    _animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
    // 修改lowerBound和upperBound默认值
    _animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
    // 监听状态
    _animation.addListener(() {
      setState(() {

      });
    });
    // 监听动画执行的状态
    _animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });
    // 执行动画
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        // 将动画的值赋值给对应的widget
        height: _animation.value,
        width: _animation.value,
        child: FlutterLogo(),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
  • AnimatedWidget优化动画

1、上面的动画要执行必须要在addListener中改变state的值
2、并且在state改变的时候,build中的widget又会重新构建

AnimatedWidget的使用需要创建一个重用动画的widget。

// 动画widget
class AnimatedLogo extends AnimatedWidget {

  AnimatedLogo(Animation animation): super(listenable: animation);
  
  Widget build(BuildContext context) {
    final Animation<double> _animation = listenable;
    return Center(
      child: Container(
        height: _animation.value,
        width: _animation.value,
        child: FlutterLogo(),
      ),
    );
  }
}

// AnimatedWidget简化
class _DemoWidgetState extends State<DemoWidget> with SingleTickerProviderStateMixin {

  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
        duration: Duration(seconds: 1), vsync: this
    );
    _animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
    _animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
    _animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedLogo(_animation);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
  • AnimatedBuilder创建动画

AnimatedWidget的缺点:
1、AnimatedWidget创建的动画每次都会创建一个widget集成AnimatedWidget
2、AnimatedWidget子类中的build中每次都会重新构建,child层级深的时候性能不好

class _DemoWidgetState extends State<DemoWidget> with SingleTickerProviderStateMixin {

  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
        duration: Duration(seconds: 1), vsync: this
    );

    _animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
    _animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
    // 监听动画执行的状态
    _animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
        animation: _animation,
        builder: ((ctx, child) {
          return Container(
            height: _animation.value,
            width: _animation.value,
            child: child,
          );
        }),
        // 这里对动画widget引用,减少构建
        child: FlutterLogo(),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
  • 并行动画

并行动画就是在同一时刻有多个状态的值在变化。

在上面动画的基础上增加透明度变化的动画。

class _DemoWidgetState extends State<DemoWidget> with SingleTickerProviderStateMixin {

  AnimationController _controller;
  Animation<double> _animation;
  Animation<double> _opacity_animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
        duration: Duration(seconds: 1), vsync: this
    );

    _animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
    _animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
    // 监听动画执行的状态
    _animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });
    // 透明度
    _opacity_animation = Tween(begin: 0.1, end: 1.0).animate(_controller);
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    print("build");
    return Center(
      child: AnimatedBuilder(
        animation: _animation,
        builder: ((ctx, child) {
          return Container(
            height: _animation.value,
            width: _animation.value,
            child: child,
          );
        }),
        child: Opacity(child: FlutterLogo(), opacity: _opacity_animation.value,),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
  • Hero动画

Hero动画指一个页面转场到下一个页面。

// 第一个页面
class DemoWidget extends StatelessWidget {

  static const HeroTag = "TestHeroTag";

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Hero(child: Image.network("https://picsum.photos/250?image=10"), tag: HeroTag,),
      onTap: () {
        Navigator.push(context, PageRouteBuilder(pageBuilder: (ctx, anim1, anim2) {
          return FadeTransition(
            opacity: anim1,
            child: NextPage(),
          );
        }));
      },
    );
  }
}

// 第二个页面
class NextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("NextPage"),),
      body: Center(
        child: GestureDetector(
            child: Hero(
              child: Image.network("https://picsum.photos/250?image=10", width: 100, height: 100,),
              tag: DemoWidget.HeroTag,),
          onTap: () {
              Navigator.pop(context);
          },
        ),
      ),
    );
  }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐