Flutter 交错动画详解
简介
交错动画是指多个动画按照一定的时间间隔依次播放的动画效果。通过合理设置动画的延迟和间隔,可以创建出富有层次感的动画效果。
基本用法
使用 Interval
dart
class StaggeredAnimationDemo extends StatefulWidget {
@override
_StaggeredAnimationDemoState createState() => _StaggeredAnimationDemoState();
}
class _StaggeredAnimationDemoState extends State<StaggeredAnimationDemo>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _opacity;
late Animation<double> _width;
late Animation<double> _height;
late Animation<EdgeInsets> _padding;
late Animation<BorderRadius?> _borderRadius;
late Animation<Color?> _color;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(milliseconds: 2000),
vsync: this,
);
_opacity = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: _controller,
curve: Interval(0.0, 0.2, curve: Curves.ease),
));
_width = Tween<double>(
begin: 50.0,
end: 200.0,
).animate(CurvedAnimation(
parent: _controller,
curve: Interval(0.2, 0.4, curve: Curves.ease),
));
_height = Tween<double>(
begin: 50.0,
end: 200.0,
).animate(CurvedAnimation(
parent: _controller,
curve: Interval(0.4, 0.6, curve: Curves.ease),
));
_padding = EdgeInsetsTween(
begin: EdgeInsets.only(bottom: 16.0),
end: EdgeInsets.only(bottom: 75.0),
).animate(CurvedAnimation(
parent: _controller,
curve: Interval(0.6, 0.8, curve: Curves.ease),
));
_borderRadius = BorderRadiusTween(
begin: BorderRadius.circular(4.0),
end: BorderRadius.circular(75.0),
).animate(CurvedAnimation(
parent: _controller,
curve: Interval(0.8, 1.0, curve: Curves.ease),
));
_color = ColorTween(
begin: Colors.blue,
end: Colors.purple,
).animate(CurvedAnimation(
parent: _controller,
curve: Interval(0.8, 1.0, curve: Curves.ease),
));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Staggered Animation')),
body: GestureDetector(
onTap: () {
if (_controller.status == AnimationStatus.completed) {
_controller.reverse();
} else {
_controller.forward();
}
},
child: Center(
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
padding: _padding.value,
alignment: Alignment.bottomCenter,
child: Opacity(
opacity: _opacity.value,
child: Container(
width: _width.value,
height: _height.value,
decoration: BoxDecoration(
color: _color.value,
borderRadius: _borderRadius.value,
),
),
),
);
},
),
),
),
);
}
}
列表交错动画
基本实现
dart
class StaggeredListDemo extends StatefulWidget {
@override
_StaggeredListDemoState createState() => _StaggeredListDemoState();
}
class _StaggeredListDemoState extends State<StaggeredListDemo>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
final List<String> _items = List.generate(20, (i) => 'Item $i');
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(milliseconds: 1000),
vsync: this,
);
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _items.length,
itemBuilder: (context, index) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
final delay = index * 0.1;
final animation = CurvedAnimation(
parent: _controller,
curve: Interval(
delay.clamp(0.0, 1.0),
(delay + 0.1).clamp(0.0, 1.0),
curve: Curves.easeOut,
),
);
return SlideTransition(
position: Tween<Offset>(
begin: Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: FadeTransition(
opacity: animation,
child: child,
),
);
},
child: ListTile(
title: Text(_items[index]),
),
);
},
);
}
}
高级用法
组合动画
dart
class CombinedStaggeredAnimation extends StatelessWidget {
final Animation<double> controller;
final Animation<double> opacity;
final Animation<double> dx;
final Animation<double> dy;
final Animation<Color?> color;
CombinedStaggeredAnimation({required this.controller})
: opacity = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: controller,
curve: Interval(0.0, 0.3, curve: Curves.ease),
)),
dx = Tween<double>(
begin: -100.0,
end: 0.0,
).animate(CurvedAnimation(
parent: controller,
curve: Interval(0.3, 0.6, curve: Curves.ease),
)),
dy = Tween<double>(
begin: -50.0,
end: 0.0,
).animate(CurvedAnimation(
parent: controller,
curve: Interval(0.6, 0.9, curve: Curves.ease),
)),
color = ColorTween(
begin: Colors.blue,
end: Colors.purple,
).animate(CurvedAnimation(
parent: controller,
curve: Interval(0.9, 1.0, curve: Curves.ease),
));
Widget _buildAnimation(BuildContext context, Widget? child) {
return Transform.translate(
offset: Offset(dx.value, dy.value),
child: Opacity(
opacity: opacity.value,
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: color.value,
borderRadius: BorderRadius.circular(10),
),
),
),
);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
builder: _buildAnimation,
animation: controller,
);
}
}
最佳实践
- 合理设置动画间隔
- 使用适当的动画曲线
- 避免过多的交错动画
- 注意性能影响
- 合理组织动画代码
注意事项
- 避免动画间隔过短
- 注意内存管理
- 处理好动画状态
- 合理设置动画时长
- 避免过度使用动画
总结
交错动画可以创建出富有层次感和韵律感的动画效果,通过合理使用可以显著提升应用的用户体验。理解并掌握交错动画的使用对于开发高质量的 Flutter 应用很有帮助。