Flutter入门:动画相关

简介: 动画在flutter中,如果想让某个widget执行动画,需要用一个动画类的widget封装一下,比如一个图片

动画


在flutter中,如果想让某个widget执行动画,需要用一个动画类的widget封装一下,比如一个图片


Center(
    child: Image.asset(xxxxxx),
),
复制代码


想实现透明度动画,使用FadeTransition,如下


Center(
  child: FadeTransition(
    opacity: _speakAnimation,
    child: Image.asset(R.assetsLiveSpeak),
  ),
),
复制代码


关键是opacity,是一个Animation,要想实现一个动画,还需要一个Tween和一个AnimationController。

Tween就是Animation。Tween还需要一个AnimationController,他们的创建及定义如下:


class _XXX extends State<XXXX>  with SingleTickerProviderStateMixin{
  AnimationController _speakController;
  Animation _speakAnimation;
  @override
  void initState() {
    super.initState();
    _speakController = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    );
    _speakAnimation = Tween(
      begin: 1.0,
      end: 0.0,
    ).animate(_speakController);
    _speakAnimation.addStatusListener((status) {   //监听动画
      if(status == AnimationStatus.completed){
        //todo
      }
    });
  }
  ...
复制代码


可以看到Tween定义的是动画的起始和结束状态(这里就是透明度的值)。而AnimationController主要是定义时长。

另外Tween可以添加动画监听(addStatusListener),一共有四种状态


enum AnimationStatus {
  /// The animation is stopped at the beginning.
  dismissed,
  /// The animation is running from beginning to end.
  forward,
  /// The animation is running backwards, from end to beginning.
  reverse,
  /// The animation is stopped at the end.
  completed,
}
复制代码


但是这样还差最后一步,启动动画,因为我们需求是页面一展示即播放,所以在build函数中forward一下即可(当然还可以在其他时机播放),代码如下:


class _XXX extends State<XXXX>  with SingleTickerProviderStateMixin{
  AnimationController _speakController;
  Animation _speakAnimation;
  @override
  void initState() {
    super.initState();
    _speakController = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    );
    _speakAnimation = Tween(
      begin: 1.0,
      end: 0.0,
    ).animate(_speakController);
    _speakAnimation.addStatusListener((status) {
      if(status == AnimationStatus.completed){
        //todo
      }
    });
  }
  ...
  Widget build(BuildContext context) {
   _speakController.forward(); //播放动画
   return Stack(
    children: <Widget>[
      Center(
        child: FadeTransition(
          opacity: _speakAnimation,
          child: Image.asset(R.assetsLiveSpeak),
        ),
      ),
      ...
复制代码


动画卡顿


从今天的一个需求说起吧,实现一个按钮呼吸效果,很简单,就是使用一个缩放动画即可,如下:


class _xxx extends State<xxx> with SingleTickerProviderStateMixin{
  AnimationController _animationController;
  Animation _animation;
  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 800),
    );
    _animation = Tween(
      begin: 0.8,
      end: 1.0,
    ).animate(_animationController);
  }
  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    _animationController.repeat(reverse: true);
    return Stack(
      alignment: Alignment.center,
      children: [
        ...
        Column(
          children: [
            ...
            ScaleTransition(
              scale: _animation,
              child: TextButton(
                onPressed: widget.onOpen,
                child: Container(
                  width: 120,
                  height: 60,
                  padding: EdgeInsets.only(bottom: 8),
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                      image: DecorationImage(
                          image: AssetImage(R.assetsLiveRedPackageBtn)
                      )
                  ),
                  child: Text(
                    "领取",
                    style: TextStyle(
                        fontSize: 22,
                        fontWeight: FontWeight.bold,
                        color: Color(0xFFB34D35)
                    ),
                  ),
                ),
              ),
            ),
            ...
          ],
        )
      ],
    );
  }
}
复制代码


动画效果是从0.8倍扩大到1.0,然后reverse,一直repeat即可。

但是运行后发现动画出现了异常,动画扩大到1.0后会快速小幅度缩放一次,然后才会还原到0.8 这明显不是我们想要的动画效果,后来我们尝试了其他动画,都有类似的效果。

但是在其他页面上的动画就不会出问题,所以最后排查发现是该页面的定时器影响到了动画。

这个页面里有一个倒计时,通过Timer来更新其中倒计时的文字,而更新使用了setState进行重绘,这样在动画执行到1秒的时候(扩大到1.0又缩回一点的时候)倒计时更新了,由于是setState,所以动画widget也重绘了(这样又变回1.0大小了),然后才缩回0.8


解决方法就是新增一个StatefulWidget类,将Timer和倒计时相关的组件放到这个类中实现,这样倒计时更新只会刷新这一部分,不会刷新动画组件,如下:


class TimerText extends StatefulWidget{
  int time;
  TimerText(this.time);
  @override
  State<StatefulWidget> createState() {
    return _TimerText();
  }
}
class _TimerText extends State<TimerText>{
  Timer timer;
  @override
  void initState() {
    super.initState();
    timer = Timer.periodic(Duration(seconds: 1), (timer) {
      setState(() {
        if(widget.time <= 0){
          timer.cancel();
        }
        else{
          widget.time--;
        }
      });
    });
  }
  @override
  void dispose() {
    timer.cancel();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Text(
      "${widget.time}s",
      style: TextStyle(
          fontSize: 14,
          color: Color(0xFFF9D873)
      ),
    );
  }
}


目录
相关文章
|
13天前
|
开发工具 UED 容器
Flutter&鸿蒙next 实现长按录音按钮及动画特效
本文介绍了如何在 Flutter 中实现一个带有动画效果的长按录音按钮。通过使用 `GestureDetector` 监听长按手势,结合 `AnimatedContainer` 和 `AnimationController` 实现按钮的动画效果,以及 `flutter_sound` 插件完成录音功能。文章详细讲解了功能需求、实现思路和代码实现,帮助读者逐步掌握这一实用功能的开发方法。
90 5
|
15天前
|
前端开发 开发者
深入探索 Flutter 鸿蒙版的画笔使用与高级自定义动画
本文深入探讨了 Flutter 中的绘图功能,重点介绍了 CustomPainter 和 Canvas 的使用方法。通过示例代码,详细讲解了如何绘制自定义图形、设置 Paint 对象的属性以及实现高级自定义动画。内容涵盖基本绘图、动画基础、渐变动画和路径动画,帮助读者掌握 Flutter 绘图与动画的核心技巧。
64 1
|
21天前
动画控制器在 Flutter 中的工作原理
【10月更文挑战第18天】总的来说,动画控制器 `AnimationController` 在 Flutter 中起着关键的作用,它通过控制动画的数值、速度、节奏和状态,实现了丰富多彩的动画效果。理解它的工作原理对于我们在 Flutter 中创建各种精彩的动画是非常重要的。
|
1月前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
74 7
|
1月前
|
UED
flutter:动画&状态管理 (十三)
本文档介绍了Flutter中`animatedList`的使用方法和状态管理的示例。`animatedList`用于创建带有动画效果的列表,示例代码展示了如何添加、删除列表项,并执行相应的动画效果。状态管理部分通过一个简单的点击切换颜色的示例,演示了如何在Flutter中管理组件的状态。
|
3月前
|
Dart 前端开发 JavaScript
Flutter&Dart-异步编程Future、Stream极速入门
Flutter&Dart-异步编程Future、Stream极速入门
72 4
Flutter&Dart-异步编程Future、Stream极速入门
|
3月前
|
前端开发
Flutter快速实现自定义折线图,支持数据改变过渡动画
Flutter快速实现自定义折线图,支持数据改变过渡动画
91 4
Flutter快速实现自定义折线图,支持数据改变过渡动画
|
3月前
|
Kubernetes Cloud Native 搜索推荐
探索云原生技术:Kubernetes入门与实践打造个性化安卓应用:从零开始的Flutter之旅
【8月更文挑战第31天】云原生技术正改变着应用开发和部署的方式。本文将带你了解云原生的基石——Kubernetes,通过实际的代码示例,从安装到部署一个简单的应用,让你迅速掌握Kubernetes的核心概念和操作方法。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你进入云原生世界的桥梁。
|
4月前
|
开发框架 Dart Java
Flutter入门进阶之旅(一)-初识Flutter
Flutter 的目标是用来创建高性能、高稳定性、高帧率、低延迟的 Android 和 iOS 应用。并且开发出来的应用在不同的平台用起来跟原生应用具有一样的体验。不同的平台的原生体验应该得到保留,让该应用看起来同整个系统更加协调。不同平台的滚动操作、字体、图标 等特殊的特性 应该和该平台上的其他应用保持一致,让用户感觉就像操作原生应用一样。
61 1
|
4月前
|
Dart 搜索推荐
Flutter入门进阶之旅(二)Hello Flutter
好像几乎我们学习或者掌握任何一门编程语言都是Hello word开始的,本篇博文做为Flutter入门进阶的第一篇分享,我们也从最简单的Hello world开始,至于Flutter开发环境的配置,跟关于Dart语言的介绍,不是该专栏要讲解的内容,我就不详细做介绍了,读者可自行google或者百度了解一下。
47 0