flutter 动画入门

简介: flutter 动画入门

flutter 动画相关的有很多类。 一开始的时候不知道怎么用。本文通过示例,逐步展示相关的类的用法。

为了展示动画原理,我们从 AnimationController 类开始。

最简单的动画

import 'package:flutter/material.dart';
void main() {
  runApp(const App());
}
class App extends StatefulWidget {
  const App({Key? key}) : super(key: key);
  @override
  State<App> createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
    _controller =
        AnimationController(duration: const Duration(seconds: 1), vsync: this)
          ..repeat()
          ..addListener(() {
            setState(() {});
          });
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Center(child: Container(
      color: Colors.green,
      width: 100 * _controller.value,
      height: 50 * _controller.value,
    ));
  }
}
复制代码

copy 上面的代码放到 main.dart里 执行,会看到一个不断放大的矩形。

_controller.value 的变化区间是 从 0 到 1。 如果想从 100,200变化呢?加一个 tween

class _AppState extends State<App> with TickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;
  @override
  void initState() {
    _controller =
        AnimationController(duration: const Duration(seconds: 1), vsync: this)
          ..repeat()
          ..addListener(() {
            setState(() {});
          });
    _animation = Tween<double>(begin: 1, end: 2).animate(_controller);
    //或这样写
    // _animation =_controller.drive(Tween<double>(begin: 1, end: 2));
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Center(
        child: Container(
      color: Colors.green,
      width: 100 * _animation.value,
      height: 50 * _animation.value,
    ));
  }
}
复制代码

也许你会问,为什么加了一个_animation。 因为 tween 的 animate 方法会生成一个 新的 Animation对象。这样新的对象把原来的 [0,1] 区间映射成 tweeen 规定的区间 做数据输出。  新对象的职责是提供数据,原来的 _controller 对动画进行控制。

目前的数据的变化是线性的,想变成 ease 呢?加一个 curve即可

_animation = Tween<double>(begin: 1, end: 2)
        .chain(CurveTween(curve: Curves.ease))
        .animate(_controller);
复制代码

这样写也是可以的

_animation = _controller
        .drive(Tween<double>(begin: 1, end: 2))
        .drive(CurveTween(curve: Curves.ease));
复制代码

至此,动画的精华就介绍完了。

动画性能

上面的示例中用的是整页刷新,为了能局部刷新 flutter 提供了两个组件

AnimatedWidget

它的作用就是把 setState 方法封装了起来,我们不用手动调用,而且把刷新限制在了 AnimatedWidget之内。下面用 AnimatedWidget 把开始的示例改造一下。

import 'package:flutter/material.dart';
void main() {
  runApp(const App());
}
class App extends StatefulWidget {
  const App({Key? key}) : super(key: key);
  @override
  State<App> createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
    _controller =
        AnimationController(duration: const Duration(seconds: 1), vsync: this)
          ..repeat();
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Center(
        child: MyWidget(
      animation: _controller,
    ));
  }
}
class MyWidget extends AnimatedWidget {
  const MyWidget({Key? key, required this.animation})
      : super(key: key, listenable: animation);
  final Animation<double> animation;
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      width: 100 * animation.value,
      height: 50 * animation.value,
    );
  }
}
复制代码

用 AnimatedWidget 就不需要再手动 setState了。但每次都需要把动画 包装成一个widget。

AnimatedBuilder

不需要把动画部分包装成 Widget。只把 build函数修改下即可。

Widget build(BuildContext context) {
   return Center(
       child: AnimatedBuilder(
     animation: _controller,
     builder: (context, _) {
       return Container(
         color: Colors.green,
         width: 100 * _controller.value,
         height: 50 * _controller.value,
       );
     },
   ));
 }
复制代码

本例中的 container没有child ,所以不会有性能问题,但是如果 container有一个复杂的child,每次都重建,这个成本还是很高的。需要优化一下

Widget build(BuildContext context) {
  var child = Container(
    color: Colors.lightBlue,
  );
  return Center(
      child: AnimatedBuilder(
    animation: _controller,
    child: child,
    builder: (context, child) {
      return Container(
        color: Colors.green,
        width: 100 * _controller.value,
        height: 50 * _controller.value,
        child: child,
      );
    },
  ));
}
}
复制代码

这里简单的用一个蓝色container做为 child,实际中可能 是一个 widget。用child参数的好处是提高性能,child 只 build 一次。

CustomPainter

对于性能要求较高的场合,可以用 CustomPainter 提高性能。

import 'package:flutter/material.dart';
void main() {
  runApp(const App());
}
class App extends StatefulWidget {
  const App({Key? key}) : super(key: key);
  @override
  State<App> createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
    _controller =
        AnimationController(duration: const Duration(seconds: 1), vsync: this)
          ..repeat();
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Center(
        child: CustomPaint(
      painter: MyPainter(animation: _controller),
      size: const Size(100, 50),
    ));
  }
}
class MyPainter extends CustomPainter {
  final Animation<double> animation;
  MyPainter({required this.animation}) : super(repaint: animation);
  @override
  void paint(Canvas canvas, Size size) {
    var rect =
        Rect.fromLTWH(0, 0, 100 * animation.value, 100 * animation.value);
    canvas.drawRect(
        rect,
        Paint()
          ..style = PaintingStyle.fill
          ..color = Colors.green);
  }
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}
复制代码

关键代码就一句 super(repaint: animation); repaint 是一个 Listenable 对象。只要有变化,就会执行重绘,与 shouldRepaint 返回值无关。

从绘制上下手,无需再 build 任何 widget,坏处是需要自己调用 canvas 绘制,成本较高。

至此,动画的核心知识就讲完了。剩下的都是锦上添花的东西了。剩下的都不知道也没有关系,知道了会方便与别人沟通。

显式动画

显式动画是指需要提供动画控制器的类

AnimatedWidget 扩展类

这些类知道名字就好,对于不好理解的我都加了链接,可以看文档,上面有动画效果或说明。

AnimatedBuilder 也是继承自 AnimatedWidget。

其它类

FadeTransition 它不是继承自 AnimatedWidget ,通过动画控制器来控制透明度。

final Animation<double> opacity;
复制代码

与之相关的是 AnimatedOpacity,和 FadeTransition 功能一样,只是不需要动画控制器。用 double数值控制透明度

final double opacity;
复制代码

隐式动画

隐式动画是指不需要提供动画控制器的类,改变属性就可以触发动画。 包括

  • AnimatedPadding
  • AnimatedAlign
  • AnimatedTheme
  • TweenAnimationBuilder
  • AnimatedPositionedDirectional
  • AnimatedPositioned
  • SliverAnimatedOpacity
  • AnimatedContainer
  • AnimatedPhysicalModel
  • AnimatedDefaultTextStyle
  • AnimatedOpacity

。一般是以 Animated 开头。

到这就差不多了,还有一些动画组件,也可以归为显示动画或隐式动画之列。

本文的目的,是为了让你对动画有一个轮廓级别的认识。知道类的作用,怎么把它们关联起来, 细节可以去查文档或看源码。

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