【动画 widget】Flutter AnimatedWidget

简介: 【动画 widget】Flutter AnimatedWidget

image.png


大家好,我是 17,今天的每日 widget 为大家介绍 AnimatedWidget。

Flutter AnimatedWidget 是一个 StatefulWidget,它的作用是当 listenalbe 变化的时候,rebuild Widget 让 UI 也随着变化。

源码分析

构造函数

const AnimatedWidget({
    super.key,
    required this.listenable,
  });
}
复制代码

AnimatedWidget 是一个抽象类,所以即使他是一个 widget,也不能直接用。 参数里面并没有 child,所有的 UI 都在 build 方法里完成。

class _AnimatedState extends State<AnimatedWidget> {
  @override
  void initState() {
    super.initState();
    widget.listenable.addListener(_handleChange);
  }
  ... 省略 didUpdateWidget,dispose
  void _handleChange() {
    setState(() {
      // The listenable's state is our build state, and it changed already.
    });
  }
  @override
  Widget build(BuildContext context) => widget.build(context);
}
复制代码

逻辑在 state 里面。_AnimatedState 就做了一件事:当 listenable(通常是 Animation 对象)变化的时候,rebuild Widget。

通过代码可以知道,AnimatedWidget 帮我们把监听的工作抽象出来,让我们再写动画的不时候省去了监听的代码。这也是抽象类的意义,把公共的部分抽离出来,减少子类的工作量。

使用 AnimatedWidget

使用 AnimatedWidget 很简单的,只需要给他一个 listenable 对象。

举一个简单的例子,不断放大的正方形。

image.png

class AnimatedBox extends AnimatedWidget {
  const AnimatedBox({Key? key, required Animation<double> listenalbe})
      : super(key: key, listenable: listenalbe);
  Animation get animation => listenable as Animation<double>;
  @override
  Widget build(BuildContext context) {
    return Container(
      width: animation.value * 100,
      height: animation.value * 100,
      color: Colors.blue[200],
    );
  }
}
复制代码
class _MyAnimationState extends State<MyAnimation>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 1))
          ..repeat();
    super.initState();
  }
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: Center(
                child: AnimatedBox(
        listenalbe: _controller.view,
    ))));
  }
}
复制代码

要注意的是 _controller 需要及时 dispose。使用 AnimatedWidget ,让我们不光省去了监听的事,还省去了 State 类。代码省去了不少,但是使用起来还是有点麻烦,还得创建 Controller,使用 ImplicitlyAnimatedWidget 可以解决这个问题。

性能优化

每当做动画效果的时候,都要认真考虑性能的问题,因为动画的刷新频率太高了,稍有不慎就会造成卡顿。有两种办法可以优化性能

我们先加一个 MyWidget,方便测试

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});
  @override
  Widget build(BuildContext context) {
    print('build');
    return Container(
      color: Colors.blue,
      width: 50,
      height: 50,
    );
  }
}
复制代码

使用 const 关键字

class AnimatedBox extends AnimatedWidget {
  const AnimatedBox({Key? key, required Animation<double> listenalbe})
      : super(key: key, listenable: listenalbe);
  Animation get animation => listenable as Animation<double>;
  @override
  Widget build(BuildContext context) {
    return Container(
      width: animation.value * 100,
      height: animation.value * 100,
      color: Colors.blue[200],
      // 新增加的代码
      child:const MyWdiget()
    );
  }
}
复制代码

加上 const 关键字后,MyWdiget 只 build  一次。

去掉 const 关键字,再看下效果。

通过 child 传进来。

class AnimatedBox extends AnimatedWidget {
  const AnimatedBox({Key? key, required Animation<double> listenalbe,required this.child})
      : super(key: key, listenable: listenalbe);
  final Widget child;
  Animation get animation => listenable as Animation<double>;
  @override
  Widget build(BuildContext context) {
    return Container(
      width: animation.value * 100,
      height: animation.value * 100,
      color: Colors.blue[200],
      child: child
    );
  }
}
复制代码
AnimatedBox(
      child: MyWidget(),
      listenalbe: _controller,
 );
复制代码

把 MyWidget() 通过 child 的方式传到 AnimatedBox 里面,即使不加 const 关键字,MyWidget 也只 build 一次。

目录
相关文章
|
17天前
深入理解Flutter鸿蒙next版本 中的Widget继承:使用extends获取数据与父类约束
本文详细介绍了Flutter中如何通过继承其他Widget来创建自定义组件。首先解释了Widget继承的基本概念,包括StatelessWidget和StatefulWidget的区别。接着通过具体示例展示了如何继承StatelessWidget和StatefulWidget,并在子类中访问父类的build方法和状态。最后,结合多个自定义Widget展示了如何在实际应用中灵活使用继承和组合来构建复杂的UI。
68 8
|
15天前
|
开发工具 UED 容器
Flutter&鸿蒙next 实现长按录音按钮及动画特效
本文介绍了如何在 Flutter 中实现一个带有动画效果的长按录音按钮。通过使用 `GestureDetector` 监听长按手势,结合 `AnimatedContainer` 和 `AnimationController` 实现按钮的动画效果,以及 `flutter_sound` 插件完成录音功能。文章详细讲解了功能需求、实现思路和代码实现,帮助读者逐步掌握这一实用功能的开发方法。
92 5
|
15天前
|
容器
flutter&鸿蒙next 使用 InheritedWidget 实现跨 Widget 传递状态
在 Flutter 中,状态管理至关重要。本文详细介绍了如何使用 InheritedWidget 实现跨 Widget 的状态传递。InheritedWidget 允许数据在 Widget 树中向下传递,适用于多层嵌套的场景。通过一个简单的计数器示例,展示了如何创建和使用 InheritedWidget,包括其基础概念、工作原理及代码实现。虽然 InheritedWidget 较底层,但它是许多高级状态管理解决方案的基础。
91 2
|
17天前
|
前端开发 开发者
深入探索 Flutter 鸿蒙版的画笔使用与高级自定义动画
本文深入探讨了 Flutter 中的绘图功能,重点介绍了 CustomPainter 和 Canvas 的使用方法。通过示例代码,详细讲解了如何绘制自定义图形、设置 Paint 对象的属性以及实现高级自定义动画。内容涵盖基本绘图、动画基础、渐变动画和路径动画,帮助读者掌握 Flutter 绘图与动画的核心技巧。
65 1
|
23天前
动画控制器在 Flutter 中的工作原理
【10月更文挑战第18天】总的来说,动画控制器 `AnimationController` 在 Flutter 中起着关键的作用,它通过控制动画的数值、速度、节奏和状态,实现了丰富多彩的动画效果。理解它的工作原理对于我们在 Flutter 中创建各种精彩的动画是非常重要的。
|
1月前
|
容器
flutter:第一个flutter&Widget的使用 (二)
本文介绍了Flutter框架下的基本组件及其用法,包括简单的 Stateless Widget 如文本和按钮,以及更复杂的 StatefulWidget 示例。详细解释了如何使用 `context` 获取祖先小部件的信息,并展示了 `MaterialApp` 的属性及用途。此外,还探讨了 `StatefulWidget` 与 `StatelessWidget` 的区别,以及 `AppBar` 的常见属性配置方法。适合Flutter初学者参考学习。
|
15天前
|
Dart JavaScript 前端开发
Flutter 的 Widget 概述与常用 Widgets 与鸿蒙 Next 的对比
Flutter 是 Google 开发的开源 UI 框架,用于快速构建高性能的移动、Web 和桌面应用。Flutter 通过 Widget 构建 UI,每个 UI 元素都是 Widget,包括文本、按钮、图片等。Widget 不仅描述外观,还描述行为,是不可变的。常见的 Widget 包括结构型(Container、Column、Row)、呈现型(Text、Image)、交互型(ElevatedButton)和状态管理型(StatefulWidget)。Flutter 与鸿蒙 Next 在组件化架构、开发语言、布局系统、性能和跨平台支持方面各有优势
67 0
|
1月前
|
UED
flutter:动画&状态管理 (十三)
本文档介绍了Flutter中`animatedList`的使用方法和状态管理的示例。`animatedList`用于创建带有动画效果的列表,示例代码展示了如何添加、删除列表项,并执行相应的动画效果。状态管理部分通过一个简单的点击切换颜色的示例,演示了如何在Flutter中管理组件的状态。
|
3月前
|
前端开发
Flutter快速实现自定义折线图,支持数据改变过渡动画
Flutter快速实现自定义折线图,支持数据改变过渡动画
93 4
Flutter快速实现自定义折线图,支持数据改变过渡动画
|
4月前
Flutter-实现头像叠加动画效果
Flutter-实现头像叠加动画效果
64 0