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)
      ),
    );
  }
}


目录
相关文章
|
1月前
|
Dart 前端开发 开发工具
【Flutter前端技术开发专栏】Flutter入门指南:搭建开发环境与第一个应用
【4月更文挑战第30天】本文介绍了Flutter SDK的安装和配置过程,以及如何创建并运行第一个Flutter应用。首先确保安装了Dart SDK和Flutter SDK,支持macOS、Linux和Windows。安装完成后,设置环境变量,然后通过`flutter doctor`验证安装。接着,使用`flutter create`命令创建新项目,进入项目目录并运行`flutter run`启动应用。在`main.dart`中修改代码以自定义应用。Flutter支持热重载和DevTools调试。本文为Flutter初学者提供了快速入门的指导。
【Flutter前端技术开发专栏】Flutter入门指南:搭建开发环境与第一个应用
|
1月前
|
数据库 Android开发
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画
|
1月前
|
前端开发 开发者 UED
【Flutter前端技术开发专栏】Flutter中的动画与过渡效果实现
【4月更文挑战第30天】Flutter UI框架以其高性能动画库著称,允许开发者轻松创建复杂动画。动画基于`Animation&lt;double&gt;`类,结合`Tween`、`Curve`和`AnimationController`实现。简单示例展示了一个点击按钮后放大效果的创建过程。此外,Flutter提供预定义动画组件和`Navigator`类实现页面过渡。`PageRouteBuilder`允许自定义过渡,而`Hero`动画则实现跨页面的平滑过渡。借助这些工具,开发者能提升应用的视觉吸引力和交互体验。
【Flutter前端技术开发专栏】Flutter中的动画与过渡效果实现
|
1月前
|
开发框架 API 开发者
Flutter的动画:实现方式与动画库的技术探索
【4月更文挑战第26天】探索Flutter动画机制与库:基础动画、自定义动画、物理动画及Lottie、AnimatedWidgets、EasyAnimations等库的应用,助开发者实现丰富动画效果,提升用户体验。同时,了解性能优化技巧,如避免重绘、利用离屏渲染和GPU加速,确保动画流畅。 Flutter为移动应用开发带来强大动画支持。
|
1月前
|
Web App开发 前端开发 iOS开发
CSS3 转换,深入理解Flutter动画原理,前端基础图形
CSS3 转换,深入理解Flutter动画原理,前端基础图形
|
1月前
|
前端开发
Flutter笔记:光影动画按钮、滚动图标卡片组等
Flutter笔记:光影动画按钮、滚动图标卡片组等
48 0
|
1月前
|
UED
Flutter之自定义路由切换动画
Flutter之自定义路由切换动画 在Flutter中,我们可以通过Navigator来实现路由管理,包括路由的跳转和返回等。默认情况下,Flutter提供了一些简单的路由切换动画,但是有时候我们需要自定义一些特殊的动画效果来提高用户体验。本文将介绍如何在Flutter中实现自定义的路由切换动画。
109 0
|
1月前
|
Dart 开发者
Flutter入门之Dart中的并发编程、异步和事件驱动详解
Flutter入门之Dart中的并发编程、异步和事件驱动详解 Dart是一种高效、快速、灵活且用于Web和移动应用程序开发的编程语言。在Dart中,支持并发编程、异步和事件驱动等特性,这些特性使得Dart在处理诸如网络请求、文件I/O、用户输入等方面表现出色。本文将详细介绍Dart中的这些特性。
|
1月前
|
开发框架
Flutter 工程化框架选择——搞定 Flutter 动画
Flutter 工程化框架选择——搞定 Flutter 动画 Flutter 是 Google 推出的跨平台移动应用开发框架,它具有快速开发、高性能、美观等优点。但是,在实际开发中,为了更好地维护和扩展代码,我们需要选择一个合适的工程化框架来协助我们进行开发。本文将介绍几种常用的 Flutter 工程化框架,并重点介绍一个搞定 Flutter 动画的方法。
|
9月前
|
Web App开发 Dart 开发工具
谷歌移动UI框架Flutter入门
谷歌移动UI框架Flutter入门