flutter hooks中的useAnimation具体如何使用
在Flutter Hooks中,useAnimation
是一个非常有用的hook,它可以让你在函数组件中更简单地使用动画。useAnimation
主要用于监听动画值的变化,并且它会在动画值变化时触发组件的重建。这里是如何使用useAnimation
的基本步骤:
- 首先,你需要一个
AnimationController
来控制动画。你可以使用useAnimationController
hook来创建和管理AnimationController
。 - 然后,使用
useAnimation
hook来监听由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>
对象不仅仅包含动画的当前值,还包含动画的状态(如是否正在进行、是否已停止等),并且它允许监听动画值的变化。当你使用useAnimation
hook时,你实际上是在利用这个Animation<double>
对象来监听动画值的变化,并且当动画值发生变化时,触发组件重建。
这意味着,你可以将这个动画值用于控制小部件属性的变化,如大小、颜色、位置等,实现丰富的动画效果。比如在上一个例子中,我们通过useAnimation
获取到的animation
值是用来控制Opacity
小部件的不透明度的。随着动画的进行,animation
的值会从0变化到1,对应地,Opacity
小部件的不透明度也会从完全透明变化到完全不透明,实现了一个淡入的效果。
总结来说,useAnimation
hook返回的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