目录
二、显式动画的核心 - AnimationController
在 Flutter 开发中,动画是提升用户体验、增强应用交互性的关键元素。其中,显式动画为开发者提供了更精细的控制能力,能实现多样化的动画效果。本文将深入剖析 Flutter 中的显式动画,结合实际代码示例,助你快速掌握这一强大的开发技巧。
一、Flutter 动画概述
Flutter 中的动画类型丰富,主要包括影视动画、显式动画、自定义影视动画、自定义显式动画以及 Hero 动画。上一篇文章讲解了影视动画,像AnimatedContainer
、AnimatedPadding
等,它们能在属性改变时自动触发动画,但控制相对有限,主要用于简单场景。而显式动画则更灵活,开发者可通过AnimationController
手动控制动画的播放、暂停等操作。
二、显式动画的核心 - AnimationController
在 Flutter 显式动画中,AnimationController
是核心角色。它不仅控制动画的启动、停止、重复等行为,还能精准调整动画的时长、速度曲线等关键属性。创建AnimationController
时,需传入vsync
参数,该参数用于使动画的刷新频率与设备屏幕保持同步,避免画面卡顿,确保流畅的视觉体验。通常,我们会通过实现SingleTickerProviderStateMixin
混入类来提供vsync
。
三、常见显式动画类型及示例
(一)RotationTransition - 元素旋转
RotationTransition
用于实现元素的旋转动画。以下是一个简单示例:
import 'package:flutter/material.dart';
class RotationTransitionPage extends StatefulWidget {
@override
_RotationTransitionPageState createState() => _RotationTransitionPageState();
}
class _RotationTransitionPageState extends State<RotationTransitionPage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
// 可在这里添加初始化时自动播放的逻辑,如 _controller.repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Rotation Transition Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
RotationTransition(
turns: _controller,
child: const FlutterLogo(size: 60),
),
const SizedBox(height: 40),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _controller.repeat(),
child: const Text('Repeat'),
),
ElevatedButton(
onPressed: () => _controller.forward(),
child: const Text('Forward'),
),
ElevatedButton(
onPressed: () => _controller.reverse(),
child: const Text('Reverse'),
),
ElevatedButton(
onPressed: () => _controller.stop(),
child: const Text('Stop'),
),
ElevatedButton(
onPressed: () => _controller.reset(),
child: const Text('Reset'),
),
],
),
],
),
),
);
}
}
在上述代码中,RotationTransition
的turns
属性接收AnimationController
对象,控制FlutterLogo
的旋转。通过点击不同按钮,可实现动画的重复播放、向前播放、向后播放、停止和重置操作。
(二)FadeTransition - 元素透明度变化
FadeTransition
用于控制元素的透明度。示例代码如下:
import 'package:flutter/material.dart';
class FadeTransitionPage extends StatefulWidget {
@override
_FadeTransitionPageState createState() => _FadeTransitionPageState();
}
class _FadeTransitionPageState extends State<FadeTransitionPage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
// 可添加初始化时自动播放逻辑
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Fade Transition Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FadeTransition(
opacity: _controller,
child: const FlutterLogo(size: 120),
),
const SizedBox(height: 40),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _controller.repeat(),
child: const Text('Repeat'),
),
ElevatedButton(
onPressed: () => _controller.forward(),
child: const Text('Forward'),
),
ElevatedButton(
onPressed: () => _controller.reverse(),
child: const Text('Reverse'),
),
ElevatedButton(
onPressed: () => _controller.stop(),
child: const Text('Stop'),
),
ElevatedButton(
onPressed: () => _controller.reset(),
child: const Text('Reset'),
),
],
),
],
),
),
);
}
}
在这个示例中,FadeTransition
的opacity
属性绑定AnimationController
,实现FlutterLogo
的透明度渐变效果。同样,通过按钮可灵活控制动画。
(三)ScaleTransition - 元素缩放
ScaleTransition
用于实现元素的放大缩小效果。代码示例如下:
import 'package:flutter/material.dart';
class ScaleTransitionPage extends StatefulWidget {
@override
_ScaleTransitionPageState createState() => _ScaleTransitionPageState();
}
class _ScaleTransitionPageState extends State<ScaleTransitionPage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
// 初始化时自动播放设置
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Scale Transition Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ScaleTransition(
scale: _controller,
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
const SizedBox(height: 40),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _controller.repeat(reverse: true),
child: const Text('Repeat'),
),
ElevatedButton(
onPressed: () => _controller.forward(),
child: const Text('Forward'),
),
ElevatedButton(
onPressed: () => _controller.reverse(),
child: const Text('Reverse'),
),
ElevatedButton(
onPressed: () => _controller.stop(),
child: const Text('Stop'),
),
ElevatedButton(
onPressed: () => _controller.reset(),
child: const Text('Reset'),
),
],
),
],
),
),
);
}
}
这里,ScaleTransition
的scale
属性与AnimationController
关联,控制红色容器的缩放。repeat(reverse: true)
可使容器在放大和缩小之间循环。
(四)SlideTransition - 元素位移
SlideTransition
用于实现元素的位移效果。由于其position
属性需借助Tween
来配置,与其他显式动画略有不同。示例代码如下:
import 'package:flutter/material.dart';
class SlideTransitionPage extends StatefulWidget {
@override
_SlideTransitionPageState createState() => _SlideTransitionPageState();
}
class _SlideTransitionPageState extends State<SlideTransitionPage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
);
// 初始化播放逻辑
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Slide Transition Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0),
end: const Offset(0.5, 0),
).animate(_controller),
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
const SizedBox(height: 40),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _controller.repeat(),
child: const Text('Repeat'),
),
ElevatedButton(
onPressed: () => _controller.forward(),
child: const Text('Forward'),
),
ElevatedButton(
onPressed: () => _controller.reverse(),
child: const Text('Reverse'),
),
ElevatedButton(
onPressed: () => _controller.stop(),
child: const Text('Stop'),
),
ElevatedButton(
onPressed: () => _controller.reset(),
child: const Text('Reset'),
),
],
),
],
),
),
);
}
}
在上述代码中,SlideTransition
的position
属性通过Tween
设置起始和结束位置,实现蓝色容器的水平位移。Offset
中的值表示位移量,x
轴为水平方向,y
轴为垂直方向。
四、控制动画的更多技巧
(一)设置动画的起始和结束值
通过AnimationController
的lowerBound
和upperBound
属性,可精确控制动画的起始和结束值。例如,在FadeTransition
中,可设置透明度从 0.5 渐变到 1:
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
lowerBound: 0.5,
upperBound: 1,
);
(二)使用 Tween 自定义动画参数
Tween
可用于更灵活地定义动画的变化范围。在ScaleTransition
中,可通过Tween
实现容器从 0.5 倍大小放大到 1.2 倍:
ScaleTransition(
scale: _controller.drive(Tween(begin: 0.5, end: 1.2)),
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
(三)修改动画的曲线效果
通过CurvedAnimation
可修改动画的速度曲线,实现不同的运动效果。如在SlideTransition
中,将动画曲线设置为Curves.bounceInOut
,使位移具有弹跳效果:
SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0),
end: const Offset(0.5, 0),
).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.bounceInOut,
),
),
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
(四)实现交错式动画
利用Interval
可创建交错式动画。例如,在SlideTransition
中,让动画在特定时间段内运动,其他时间静止:
SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0),
end: const Offset(0.5, 0),
).animate(
CurvedAnimation(
parent: _controller,
curve: Interval(0.2, 0.8, curve: Curves.bounceInOut),
),
),
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
上述代码中,动画将在总时长的 20% 到 80% 时间段内执行,且具有弹跳效果。
五、总结
Flutter 的显式动画为开发者提供了丰富的创作空间,通过AnimationController
和各种动画组件,能实现旋转、透明度变化、缩放、位移等多样化效果,并可精细控制动画的各个方面。希望本文的内容能帮助你在 Flutter 开发中熟练运用显式动画,打造出更具吸引力和交互性的应用程序。