likes
comments
collection
share

flutter hooks中的useAnimation具体如何使用

作者站长头像
站长
· 阅读数 45

在Flutter Hooks中,useAnimation是一个非常有用的hook,它可以让你在函数组件中更简单地使用动画。useAnimation主要用于监听动画值的变化,并且它会在动画值变化时触发组件的重建。这里是如何使用useAnimation的基本步骤:

  1. 首先,你需要一个AnimationController来控制动画。你可以使用useAnimationControllerhook来创建和管理AnimationController
  2. 然后,使用useAnimationhook来监听由AnimationController驱动的动画值的变化。

下面是一个使用useAnimationuseAnimationController的示例:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

class MyAnimatedWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    // 创建并初始化AnimationController
    final controller = useAnimationController(
      duration: const Duration(seconds: 2), // 动画持续时间
    );

    // 启动动画
    useEffect(() {
      controller.forward();
      return null; // 由于这里不需要在组件卸载时执行任何操作,因此返回null
    }, [controller]);

    // 使用useAnimation监听动画值的变化
    final animation = useAnimation(controller);

    // 根据动画值构建UI
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Hooks Example'),
      ),
      body: Center(
        child: Opacity(
          opacity: animation, // 直接使用animation作为不透明度的值
          child: Container(
            width: 200,
            height: 200,
            color: Colors.blue,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (controller.isAnimating) {
            controller.stop();
          } else {
            controller.repeat(reverse: true);
          }
        },
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的动画,其中一个蓝色的正方形在两秒内逐渐变得不透明。我们使用useAnimationController来创建动画控制器,并通过useEffect在组件构建完成后启动动画。随后,我们使用useAnimation来监听动画值的变化,并将这个值用作Opacity小部件的不透明度,从而实现渐变效果。我们还添加了一个浮动操作按钮来控制动画的播放和停止。

希望这个示例能帮助你理解如何在Flutter Hooks中使用useAnimation

得到的animation到底是什么呢?

useAnimation中得到的animation是一个Animation<double>类型的对象。这个对象代表了动画的当前值,它是随时间变化的。在Flutter中,动画通常是通过一个从0到1的值来表示的,其中0代表动画的开始状态,1代表动画的结束状态。这个值可以是线性变化的,也可以是非线性变化的,这取决于动画的Curve

Animation<double>对象不仅仅包含动画的当前值,还包含动画的状态(如是否正在进行、是否已停止等),并且它允许监听动画值的变化。当你使用useAnimationhook时,你实际上是在利用这个Animation<double>对象来监听动画值的变化,并且当动画值发生变化时,触发组件重建。

这意味着,你可以将这个动画值用于控制小部件属性的变化,如大小、颜色、位置等,实现丰富的动画效果。比如在上一个例子中,我们通过useAnimation获取到的animation值是用来控制Opacity小部件的不透明度的。随着动画的进行,animation的值会从0变化到1,对应地,Opacity小部件的不透明度也会从完全透明变化到完全不透明,实现了一个淡入的效果。

总结来说,useAnimationhook返回的animation对象,是一个随时间变化的Animation<double>类型的值,你可以利用这个值来控制小部件属性的动态变化,实现动画效果。

通过useAnimationController创建的动画,页面关闭后,会释放动画资源吧?

是的,在使用flutter_hooks库中的useAnimationController创建动画控制器时,页面(或者说是HookWidget)关闭后,动画资源会被自动释放。这是因为flutter_hooks利用Flutter的生命周期管理,确保在不需要时释放资源,减少内存泄漏的风险。

useAnimationController是一个特别为hooks设计的API,它在底层自动处理了AnimationController的创建和销毁。当HookWidget被移除出widget树时,由useAnimationController创建的AnimationController会自动调用其dispose方法,从而释放与之相关的资源。

这个自动管理资源的特性使得开发者可以更专注于动画逻辑的实现,而不用担心资源管理的问题。这也展示了使用hooks相较于传统的StatefulWidget在资源管理方面的一些优势。

简单来说,通过useAnimationController创建的动画控制器在组件卸载时会自动调用dispose方法,开发者不需要手动管理这部分资源的释放。

useAnimationController创建的controller上有哪些属性?详细解释

useAnimationController创建的AnimationController是Flutter动画库中的一个非常核心的类,它继承自Animation<double>,用于控制时间和动画序列。这个控制器提供了多种属性和方法来管理动画,以下是一些最重要的属性:

1. value

  • 类型: double
  • 描述: 当前动画的值。对于标准的动画控制器,这个值通常在0.0到1.0之间,表示动画的当前进度。

2. duration

  • 类型: Duration
  • 描述: 动画的持续时间。这是完成动画所需的总时间。

3. reverseDuration

  • 类型: Duration?
  • 描述: 动画反向执行的持续时间。如果未指定,则使用duration

4. debugLabel

  • 类型: String?
  • 描述: 用于调试的标签。这个标签在调试动画时很有用,特别是当有很多动画控制器时。

5. view

  • 类型: Animation
  • 描述: 一个代表控制器自己的动画对象。可以用来读取当前动画值或监听动画变化。

6. lowerBound

  • 类型: double
  • 描述: 动画值的下界,默认为0.0。

7. upperBound

  • 类型: double
  • 描述: 动画值的上界,默认为1.0。

8. status

  • 类型: AnimationStatus
  • 描述: 当前动画的状态,如dismissed(未开始)、forward(向前)、reverse(向后)、completed(完成)。

9. velocity

  • 类型: double
  • 描述: 动画的当前速度,以单位值每秒为单位。

10. isAnimating

  • 类型: bool
  • 描述: 是否有动画正在进行。当动画前进或后退时为true。

11. isCompleted

  • 类型: bool
  • 描述: 动画是否已到达终点。

12. isDismissed

  • 类型: bool
  • 描述: 动画是否处于起始点。

13. animationBehavior

  • 类型: AnimationBehavior
  • 描述: 当在动画控制器处于非活动状态时(例如,窗口处于后台),动画的行为。默认为AnimationBehavior.normal,在某些情况下(例如测试),可以设置为AnimationBehavior.preserve以改变此行为。

AnimationController还提供了丰富的方法来控制动画的播放,如forward()reverse()stop()repeat()reset()等,允许开发者灵活地实现各种动画效果。通过addListener()addStatusListener()方法,可以监听动画值的改变和动画状态的改变,从而实现更复杂的动画逻辑。

详细介绍各个属性的使用,并举例说明

下面详细介绍了AnimationController的几个关键属性,并通过示例来说明它们的使用。

value

  • 描述: 表示动画的当前值,通常在lowerBoundupperBound之间变化。
  • 示例:
final controller = useAnimationController(
  duration: const Duration(seconds: 1),
);
// 获取当前动画值
double currentValue = controller.value;

duration & reverseDuration

  • 描述duration是动画正向执行的持续时间,reverseDuration是动画反向执行的持续时间。
  • 示例:
final controller = useAnimationController(
  duration: const Duration(seconds: 2), // 正向持续2秒
  reverseDuration: const Duration(seconds: 1), // 反向持续1秒
);

debugLabel

  • 描述: 用于调试的标签,帮助识别动画控制器。
  • 示例:
final controller = useAnimationController(
  duration: const Duration(seconds: 1),
  debugLabel: 'demoAnimation',
);

status

  • 描述: 表示动画的当前状态,如AnimationStatus.forwardAnimationStatus.reverseAnimationStatus.completedAnimationStatus.dismissed
  • 示例:
final controller = useAnimationController(
  duration: const Duration(seconds: 1),
);
controller.addStatusListener((status) {
  if (status == AnimationStatus.completed) {
    print("动画完成");
  }
});

isAnimating

  • 描述: 表示动画是否正在进行中。
  • 示例:
final controller = useAnimationController(
  duration: const Duration(seconds: 1),
);
if (controller.isAnimating) {
  print("动画正在进行中");
}

isCompleted & isDismissed

  • 描述isCompleted表示动画是否已到达终点,isDismissed表示动画是否处于起始点。
  • 示例:
final controller = useAnimationController(
  duration: const Duration(seconds: 1),
);
controller.forward();
controller.addStatusListener((status) {
  if (controller.isCompleted) {
    print("动画已完成");
  }
  if (controller.isDismissed) {
    print("动画已重置到初始状态");
  }
});

使用示例

下面是一个综合示例,展示了如何创建一个AnimationController,并使用它来控制一个小部件的透明度从完全透明渐变到完全不透明。

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

class FadeInWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final controller = useAnimationController(
      duration: const Duration(seconds: 2),
    );

    // 开始动画
    useEffect(() {
      controller.forward();
      return null;
    }, [controller]);

    final animation = useAnimation(controller);

    return Scaffold(
      body: Center(
        child: Opacity(
          opacity: animation, // 使用controller的值来控制不透明度
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个FadeInWidget,它使用useAnimationController来控制一个蓝色方块的透明度。动画持续时间设置为2秒,当组件被插入到树中时,透明度会从0(完全透明)渐变到1(完全不透明)。

如何手动开启动画,而不是组件Build的时候就立马开启

如果想要手动控制动画的开始,而不是在组件构建(Build)的时候就立即开始,你可以将动画的启动逻辑放在某个事件的回调函数中,比如按钮点击事件。这样,只有当该事件被触发时,动画才会开始。以下是一个简单的示例,展示了如何通过点击一个按钮来启动动画:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

class ManualAnimationWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    // 使用useAnimationController创建一个AnimationController
    final controller = useAnimationController(
      duration: const Duration(seconds: 2), // 设置动画持续时间为2秒
    );

    // 使用useAnimation来监听AnimationController,这样可以在动画值改变时重新构建组件
    final animation = useAnimation(controller);

    return Scaffold(
      appBar: AppBar(
        title: Text("手动控制动画示例"),
      ),
      body: Center(
        child: Opacity(
          opacity: animation, // 使用动画控制器的当前值作为不透明度值
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 当按钮被点击时,开始或重置动画
          if (controller.isAnimating) {
            controller.reset();
          } else {
            controller.forward();
          }
        },
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}

在这个示例中,我们创建了一个名为ManualAnimationWidgetHookWidget,它包含一个使用useAnimationController创建的AnimationController。我们没有在组件构建时就开始动画,而是提供了一个浮动操作按钮,当这个按钮被点击时,会检查动画是否正在运行。如果动画正在运行,我们会调用controller.reset()来重置动画;如果动画没有运行,我们会调用controller.forward()来启动动画。

这样,动画的控制就完全由用户通过点击按钮来手动管理,而不是自动在组件构建时开始。这种方式可以让你更灵活地控制动画的开始时机,适用于需要用户交互来触发动画的场景。

为什么在代码中要执行这个:useAnimation(animationController);

在Flutter中使用flutter_hooks库时,useAnimation是一个与useAnimationController配合使用的Hook,它的作用是让你的widget在动画值改变时能够自动重建(rebuild)。这对于创建平滑动画效果是非常重要的,因为动画本质上是随时间变化的一系列帧,每一帧的显示都可能不同。

当你使用useAnimationController创建一个AnimationController时,这个控制器本身是一个Animation<double>,它会在动画的每一帧生成新的值。然而,仅仅有这个控制器并不足以使得widget在控制器的值改变时重新绘制自己,这就是useAnimation发挥作用的地方。

通过调用useAnimation(animationController),你实际上是告诉Flutter:“嘿,这里有一个动画,当这个动画的值改变时,请重新绘制我。”这样,每当animationController的值发生变化时,使用useAnimation的widget就会自动重建,确保动画的每一帧都能被正确渲染到屏幕上。

示例

为了更好地理解,让我们看一个简单的例子:

Dart
1import 'package:flutter/material.dart';
2import 'package:flutter_hooks/flutter_hooks.dart';
3
4class FadeInWidget extends HookWidget {
5  @override
6  Widget build(BuildContext context) {
7    // 创建一个AnimationController
8    final controller = useAnimationController(
9      duration: const Duration(seconds: 2), // 动画时长为2秒
10    );
11
12    // 使用useAnimation来确保widget在动画值改变时能重新绘制
13    final animation = useAnimation(controller);
14
15    // 在某个事件(比如这里的按钮点击)中启动动画
16    useEffect(() {
17      controller.forward();
18      return controller.dispose;
19    }, [controller]);
20
21    return Opacity(
22      opacity: animation, // 使用animation作为不透明度的值
23      child: Container(
24        width: 200,
25        height: 200,
26        color: Colors.blue,
27      ),
28    );
29  }
30}

在这个示例中,我们使用useAnimationController创建了一个动画控制器,并通过useEffect在widget第一次构建时启动动画。然后,我们使用useAnimation来监听这个控制器的值。每当controller的动画值发生变化时,useAnimation都会触发widget的重建,从而更新Opacity widget的不透明度属性,实现淡入效果。

总的来说,useAnimation是一个使动画与widget的UI表现保持同步的重要工具,它确保了动画的每一帧都能被正确渲染。

转载自:https://juejin.cn/post/7366076727566483508
评论
请登录