Flutter(十五)——动画的封装与简化

简介: Flutter(十五)——动画的封装与简化

前言


在上一篇的动画内容中,我们学习了基本的概念,以及动画的基本使用规则,但是,上一篇的代码真的实际项目中应用很多吗?其实不是,上一篇之所以那么介绍,只是为了让大家更了解Flutter动画的原理,其实还有更简单封装与简化的使用方式,这一篇就开始学习这些内容。


AnimatedWidget


前面动画之中,我们都是通过addListener和setState来更新UI的,然而有时候可以不用这么麻烦,通过AnimationWidget这个类就可以实现,它对addListener和setState进行了封装,隐藏了实现细节。下面,我们直接上代码来看看:

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
  Animation<double> animation;
  AnimationController controller;
  initState(){
    super.initState();
    controller=AnimationController(duration: const Duration(milliseconds: 2000),vsync: this);
    animation=CurvedAnimation(parent: controller,curve: Curves.bounceIn)..addStatusListener((status){
      if(status==AnimationStatus.completed){//动画在结束时停止的状态
        controller.reverse();//颠倒
      }else if(status==AnimationStatus.dismissed){//动画在开始时就停止的状态
        controller.forward();//向前
      }
    })..addListener((){
      setState(() {
        print(animation.value);
      });
    });
    controller.forward();
  }
  @override
  void dispose() {
    controller.dispose();
    // TODO: implement dispose
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return AnimationLogo(animation: animation,);
  }
}
class AnimationLogo extends AnimatedWidget{
  AnimationLogo({Key key,Animation<double> animation})
      :super(key:key,listenable:animation);
  @override
  Widget build(BuildContext context) {
    final Animation<double> animation=listenable;
    return Scaffold(
      appBar: AppBar(
        title: Text("封装动画"),
      ),
      body: Container(
        height: animation.value*300,
        margin: EdgeInsets.symmetric(vertical: 10.0),
        width: animation.value*300,
        child: FlutterLogo(),
      ),
    );
  }
}


封装后,AnimationLogo可以通过当前自身Animation的value值来绘制自己。


AnimatedBuilder


有时候我们会使用多个AnimatedWidget,而如果多次实现AnimatedWidget,则代码就显得不那么美观了,这个时候,我们就需要考虑使用AnimatedBuilder,它的优点有:


(1)不需要知道如何渲染组件,也不需要知道如何管理动画对象


(2)继承自AnimatedWidget,可以直接当作组件来使用,且不用显式地去添加帧的监听addListener(…),然后在调用setState


(3)只调用动画组件中地build,在复杂地布局下性能有所提高


我们先来看一张组件示意图:


接着我们将上面的代码进行重构,代码如下:

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
  Animation<double> animation;
  AnimationController controller;
  initState(){
    super.initState();
    controller=AnimationController(duration: const Duration(milliseconds: 2000),vsync: this);
    animation=CurvedAnimation(parent: controller,curve: Curves.bounceIn)..addStatusListener((status){
      if(status==AnimationStatus.completed){//动画在结束时停止的状态
        controller.reverse();//颠倒
      }else if(status==AnimationStatus.dismissed){//动画在开始时就停止的状态
        controller.forward();//向前
      }
    })..addListener((){
      setState(() {
      });
    });
    controller.forward();
  }
  @override
  void dispose() {
    controller.dispose();
    // TODO: implement dispose
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return GrowTransition(child:AnimationLogo(),animation: animation,);
  }
}
class AnimationLogo extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      margin: EdgeInsets.symmetric(vertical: 10),
      child: FlutterLogo(),
    );
  }
}
class GrowTransition extends StatelessWidget{
  final Widget child;
  final Animation<double> animation;
  GrowTransition({this.child,this.animation});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("AnimatedBuilder"),),
      body: Center(
        child: AnimatedBuilder(
          animation: this.animation,
          builder: (BuildContext context,Widget child){
            return Container(
              height: animation.value*300,
              width: animation.value*300,
              child: child,
            );
          },
          child: this.child,
        ),
      ),
    );
  }
}


前面的代码基本一样,就是后面的代码变更了,所以重点看后面的代码就行。其实在Flutter开发中,通过AnimatedBuilder方式还封装了很多动画,比如SizeTransition,ScaleTransition,RotationTransition,FadeTransition,FractionalTranslation等。很多时候我们都可以反复使用这些预置的过渡类。效果图更前篇文章差不多,这里就不展示了。

相关文章
|
10月前
|
存储 缓存 JavaScript
Flutter 学习之封装 WebView
【10月更文挑战第24天】通过以上的探讨,我们可以看出,在 Flutter 中封装 WebView 是非常有必要的,它可以提高代码的复用性、增强可维护性、提供统一接口。在实际应用中,我们需要根据具体的需求和场景,选择合适的封装方法和技术,以实现更好的效果。
|
11月前
动画控制器在 Flutter 中的工作原理
【10月更文挑战第18天】总的来说,动画控制器 `AnimationController` 在 Flutter 中起着关键的作用,它通过控制动画的数值、速度、节奏和状态,实现了丰富多彩的动画效果。理解它的工作原理对于我们在 Flutter 中创建各种精彩的动画是非常重要的。
203 60
|
9月前
|
XML JSON 前端开发
一文带你了解 Flutter dio封装
一文带你了解 Flutter dio封装
1265 1
|
10月前
|
开发工具 UED 容器
Flutter&鸿蒙next 实现长按录音按钮及动画特效
本文介绍了如何在 Flutter 中实现一个带有动画效果的长按录音按钮。通过使用 `GestureDetector` 监听长按手势,结合 `AnimatedContainer` 和 `AnimationController` 实现按钮的动画效果,以及 `flutter_sound` 插件完成录音功能。文章详细讲解了功能需求、实现思路和代码实现,帮助读者逐步掌握这一实用功能的开发方法。
392 5
|
10月前
|
存储 缓存 Dart
Flutter&鸿蒙next 封装 Dio 网络请求详解:登录身份验证与免登录缓存
本文详细介绍了如何在 Flutter 中使用 Dio 封装网络请求,实现用户登录身份验证及免登录缓存功能。首先在 `pubspec.yaml` 中添加 Dio 和 `shared_preferences` 依赖,然后创建 `NetworkService` 类封装 Dio 的功能,包括请求拦截、响应拦截、Token 存储和登录请求。最后,通过一个登录界面示例展示了如何在实际应用中使用 `NetworkService` 进行身份验证。希望本文能帮助你在 Flutter 中更好地处理网络请求和用户认证。
458 1
|
10月前
|
前端开发 开发者
深入探索 Flutter 鸿蒙版的画笔使用与高级自定义动画
本文深入探讨了 Flutter 中的绘图功能,重点介绍了 CustomPainter 和 Canvas 的使用方法。通过示例代码,详细讲解了如何绘制自定义图形、设置 Paint 对象的属性以及实现高级自定义动画。内容涵盖基本绘图、动画基础、渐变动画和路径动画,帮助读者掌握 Flutter 绘图与动画的核心技巧。
247 1
|
10月前
|
Dart UED 开发者
Flutter&鸿蒙next中的按钮封装:自定义样式与交互
在Flutter应用开发中,按钮是用户界面的重要组成部分。Flutter提供了多种内置按钮组件,但有时这些样式无法满足特定设计需求。因此,封装一个自定义按钮组件变得尤为重要。自定义按钮组件可以确保应用中所有按钮的一致性、可维护性和可扩展性,同时提供更高的灵活性,支持自定义颜色、形状和点击事件。本文介绍了如何创建一个名为CustomButton的自定义按钮组件,并详细说明了其样式、形状、颜色和点击事件的处理方法。
221 1
|
10月前
|
开发工具 UED
Flutter&鸿蒙next中封装一个输入框组件
本文介绍了如何创建一个简单的Flutter播客应用。首先,通过`flutter create`命令创建项目;接着,在`lib`目录下封装一个自定义输入框组件`CustomInput`;然后,在主应用文件`main.dart`中使用该输入框组件,实现简单的UI布局和功能;最后,通过`flutter run`启动应用。本文还提供了后续扩展建议,如状态管理、网络请求和UI优化。
181 1
|
前端开发
Flutter快速实现自定义折线图,支持数据改变过渡动画
Flutter快速实现自定义折线图,支持数据改变过渡动画
294 4
Flutter快速实现自定义折线图,支持数据改变过渡动画
|
10月前
|
开发工具
Flutter&鸿蒙next中封装一个列表组件
Flutter&鸿蒙next中封装一个列表组件
162 0