flutter中的动画效果_Flutter中的基本动画

news/2024/7/6 0:11:11

flutter中的动画效果

While Flutter has an enormous amount of amazing packages for creating animation effects for your apps, there are also built-in methods for manually creating more fine-tuned animations.

尽管Flutter提供了大量令人惊叹的软件包,可为您的应用创建动画效果,但也有内置方法可用于手动创建更多微调的动画。

先决条件 (Prerequisites)

For our cross-screen animations I’ll be assuming that you already know how to create basic routes, just to keep things brief. You can review the docs here if you’re not comfortable with that just yet.

对于我们的跨屏动画,我假设您已经知道如何创建基本路线,只是为了使内容简短。 如果您还不满意,可以在这里查看文档 。

线性动画 (Linear Animations)

The main three parts of our animations are the ticker to control our time, the controller to register our parameters like our duration, and then the values we want changed. Before our widget is rendered, in our initState, we can set our controller to its parameters, set its direction, and add a listener to reset our widgets state with every change.

动画的主要三个部分是控制时间的ticker ,用于注册诸如持续时间之类的参数的controller ,然后是我们想要更改的值。 在呈现窗口小部件之前,可以在initState控制器设置为其参数,设置其方向,并添加一个侦听器以在每次更改时重置窗口小部件的状态。

By default a controller will move change from 0 to 1 in the time we set for our duration, we can print our controller.value in our listener to watch this happen. We can change our default start and end values by setting the upperBound or lowerBound properties.

默认情况下,控制器会在我们为持续时间设置的时间内将更改从0移动到1,我们可以在监听controller.value中打印controller.value来观察这种情况。 我们可以通过设置upperBoundlowerBound属性来更改默认的开始值和结束值。

main.dart
main.dart
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  AnimationController controller;

  void initState() {
    super.initState();
    controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this); // Links this controller to this widget so it won't run if the parent widget isn't rendered, to save on resources.

    controller.forward();
    controller.addListener(() => setState(() {}));
  }
}

To use our animation we just need to set whatever we want, like opacity, to controller.value.

要使用动画,我们只需要将所需的内容(如不透明度)设置为controller.value

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Opacity(
          opacity: controller.value,
          child: Container(width: 50, height: 50, color: Colors.red),
        ),
      ),
    );
  }

弯曲动画 (Curved Animations)

Instead of boring linear animations we can use different curved variations to control exactly how our controller changes. To do this we can user CurvedAnimation to create a kind of wrapper over our original controller. This wrapper will take its parent, our controller, and the curve we want to apply. When using a curved animation we can’t have lower and upper bounds besides 0 and 1, so when we apply it we can just multiply its value. There’s a really extensive list of options over in the docs.

代替无聊的线性动画,我们可以使用不同的曲线变化来精确控制控制器的变化方式。 为此,我们可以使用CurvedAnimation在原始控制器上创建一种包装器。 该包装器将使用其父级,控制器和我们要应用的曲线。 使用弯曲动画时,除0和1外,不能有上限和下限,因此应用它时,我们可以将其值相乘。 在docs中有很多选项。

Another useful method on controller is addStatusListener, which will allow us to tap into its lifecycle. Our controller triggers a completed or dismissed event whenever it’s value has reached its upper or lower bound. We can use this with its forward and reverse methods to loop our animation infinitely.

controller上的另一个有用方法是addStatusListener ,它使我们能够利用其生命周期。 每当其值达到其上限或下限时,我们的控制器就会触发一个完成或被取消的事件。 我们可以使用它的forwardreverse方法无限循环播放动画。

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation animation;

  void initState() {
    super.initState();
    controller = AnimationController(
        duration: Duration(seconds: 1), 
        vsync: this);
    animation = CurvedAnimation(parent: controller, curve: Curves.slowMiddle);

    controller.forward();
    animation.addListener(() => setState(() {}));

    controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) controller.reverse(from: 400);
      else if (status == AnimationStatus.dismissed) controller.forward();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          margin: EdgeInsets.only(bottom: animation.value * 400),
          width: 50,
          height: 50,
          color: Colors.red),
      ),
    );
  }
}

补间 (Tweens)

Instead of just working with number values, we can also work with ranges of other things, like colors, using tweens (short for between). Like with our curved animation, it will act as a wrapper for our controller or animation and we can set our color to its value.

我们不仅可以使用数字值,还可以使用补间(tweens)来处理其他范围,例如颜色。 与弯曲动画一样,它将用作控制器或动画的包装,我们可以将颜色设置为其值。

main.dart
main.dart
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation animation;
  Animation changeColor;

  void initState() {
    super.initState();
    controller =
        AnimationController(duration: Duration(seconds: 1), vsync: this);
    animation = CurvedAnimation(parent: controller, curve: Curves.slowMiddle);
    changeColor = ColorTween(begin: Colors.red, end: Colors.blue).animate(animation);
    controller.forward();
    animation.addListener(() => setState(() {}));

    controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) controller.reverse(from: 400);
      else if (status == AnimationStatus.dismissed) controller.forward();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          margin: EdgeInsets.only(bottom: animation.value * 400),
          width: 50,
          height: 50,
          color: changeColor.value),
      ),
    );
  }
}

十字屏 (Cross Screen)

Another awesome technique is to use the Hero widget when we want a transition between widgets on different screens. We just need to wrap each in its own Hero widget with matching tags. The tags must be unique and there cannot be more than one on the screen at any time.

另一个很棒的技术是当我们想要在不同屏幕上的小部件之间进行转换时使用Hero小部件。 我们只需要使用匹配的标签将它们包装在自己的Hero小部件中即可。 标签必须唯一,并且屏幕上任何时候都不能超过一个。

firstScreen
firstScreen
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
      SizedBox(height: 1),
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          Hero(tag: 'icon', child: Icon(Icons.add)),
        ]),
      Navbar()
  ]));
}
secondScreen
secondScreen
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        SizedBox(height: 1),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
            SizedBox(width: 1),
            Hero(
              tag: 'icon',
              child: Icon(Icons.add, color: Colors.red, size: 75)),
          ]),
        Navbar()
      ]),
  );
}

结论 (Conclusion)

With most frontend web technologies from the past, animations were left as an after-thought, but the flutter team did an amazing job at keeping animations in mind when developing this amazing framework. We really only scratched the surface of what Flutter is capable of in terms of animations.

在过去使用大多数前端Web技术的情况下,动画是事后才想到的,但是在开发这个令人惊叹的框架时,颤抖的团队在将动画铭记在心方面做得非常出色。 我们真的只是从动画的角度介绍了Flutter的功能。

翻译自: https://www.digitalocean.com/community/tutorials/flutter-animations-in-flutter

flutter中的动画效果


http://www.niftyadmin.cn/n/3649783.html

相关文章

Android使用SharedPreferneces存储数据

Android使用SharedPreferneces存储数据 实现效果&#xff1a; java代码&#xff1a; package com.henu.sharedpreferences;import androidx.appcompat.app.AppCompatActivity;import android.content.Context; import android.content.SharedPreferences; import android.os.…

typescript 模块_TypeScript中的模块增强

typescript 模块Before getting into module augmentation, let’s look at some TypeScript merging principles which will become useful as we progress. 在进行模块扩充之前&#xff0c;让我们看一下一些TypeScript合并原理&#xff0c;这些原理将随着我们的进步而变得有用…

阴阳怕懵懂吗?

阴阳怕懵懂吗&#xff1f;郑昀 20060621 最近看来势必要有一批人跟着麦田的《 阴阳怕懵懂&#xff0c;说说“无名小站” - 麦田的读书生活 》和方兴东的《 创业者最核心的品质是什么&#xff1f;对模糊性的高度容忍--方兴东观察》的博文继续往下谈。嗯&#xff0c;这就是话题的…

Android开发使用SQLite数据库和Listview实现数据的存储与展示

Android开发使用SQLite数据库和Listview实现数据的存储与展示 实现效果&#xff1a; 使用了SimpleCursorAdapter方便数据库和listview之间的数据传递。 MainActivity.java&#xff1a; package com.henu.saveindatabase;import androidx.appcompat.app.AppCompatActivity;i…

js更改css属性_CSS会更改属性:何时以及何时不使用它

js更改css属性The will-change CSS property is commonly misunderstood or not used correctly, in this short post I will demystify the property so you can make your CSS animations and transitions as performant as possible. will-change CSS属性通常被误解或使用不…

在不断地试错中调整向前

在不断地试错中调整向前郑昀 20060619 几个月前的这两篇文章《Web2.0创业&#xff1a;程序员的创业&#xff1f; - 玩火者的自白 - 邱致中的IT博客》和《Web2.0创业&#xff1a;需要什么样的团队》说的模模糊糊&#xff0c;我们看得也是懵懵懂懂。本来许多事情就是要在不断地…

contentProviderSample实现操作数据库

contentProviderSample实现操作数据库并显示在listview控件中。 实现效果和上个实验相同&#xff1a; 点击进入上个实验 本实验在上个实验基础上完成&#xff0c;与上个实验包名略有不同&#xff0c;并且添加了ContentProvider.java文件、修改了MainActivity.java的代码。 Con…

node.js入门_Node.js中的压缩入门

node.js入门Compression in Node.js and Express decreases the downloadable amount of data that’s served to users. Through the use of this compression, we can improve the performance of our Node.js applications as our payload size is reduced drastically. Nod…