flutter hooks中的useAnimation具体如何使用
在Flutter Hooks中,useAnimation是一个非常有用的hook,它可以让你在函数组件中更简单地使用动画。useAnimation主要用于监听动画值的变化,并且它会在动画值变化时触发组件的重建。这里是如何使用useAnimation的基本步骤:
- 首先,你需要一个
AnimationController来控制动画。你可以使用useAnimationControllerhook来创建和管理AnimationController。 - 然后,使用
useAnimationhook来监听由AnimationController驱动的动画值的变化。
下面是一个使用useAnimation和useAnimationController的示例:
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
- 描述: 表示动画的当前值,通常在
lowerBound和upperBound之间变化。 - 示例:
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.forward、AnimationStatus.reverse、AnimationStatus.completed、AnimationStatus.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),
),
);
}
}
在这个示例中,我们创建了一个名为ManualAnimationWidget的HookWidget,它包含一个使用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