概述
前几篇文章我们都是使用Flutter中的AnimationController、Animation以及Tween来实现我们的动画效果,如果我们只想实现一些简单动画,该怎么办呢?今天我们就一起了解Flutter中内置的动画组件.接下来,我们就来分类来看一下Futter内置的动画组件.
- 需要外部Animation支持
Animation组件 | 功能 |
---|---|
DecoratedBoxTransition | DecoratedBox的动画版本,可以给它的Decoration不同属性使用动画 |
FadeTransition | 对透明度使用动画的widget |
PositionedTransition | Positioned的动画版本,它需要一个特定的动画来将孩子的位置从动画的生命周期的起始位置移到结束位置。 |
RotationTransition | 对widget使用旋转动画 |
ScaleTransition | 对widget使用缩放动画 |
SizeTransition | 对widget使用尺寸相关动画 |
SlideTransition | 对相对于其正常位置的某个位置之间使用动画 |
- 不需要外部Animation支持
Animation组件 | 功能 |
---|---|
AnimatedPadding | 在padding发生变化时会执行过渡动画到新状态 |
AnimatedPositioned | 配合Stack一起使用,当定位状态发生变化时会执行过渡动画到新的状态。 |
AnimatedOpacity | Opacity的动画版本,在给定的透明度变化时,自动地在给定的一段时间内改变child的Opacity |
AnimatedAlign | 当alignment发生变化时会执行过渡动画到新的状态。 |
AnimatedContainer | 当Container属性发生变化时会执行过渡动画到新的状态。 |
AnimatedDefaultTextStyle | 当字体样式发生变化时,子组件中继承了该样式的文本组件会动态过渡到新样式。 |
本篇文章大部分示例直接摘抄官方,具体可去 动画&Motion Widget 查询.(PS:写不动了,着实写不动了. )
需要外部Animation支持的组件示例
DecoratedBoxTransition示例
final DecorationTween decorationTween = DecorationTween(
begin: BoxDecoration(
color: const Color(0xFFFFFFFF),
border: Border.all(style: BorderStyle.none),
borderRadius: BorderRadius.circular(60.0),
shape: BoxShape.rectangle,
boxShadow: const [
BoxShadow(
color: Color(0x66666666),
blurRadius: 10.0,
spreadRadius: 3.0,
offset: Offset(0, 6.0),
)
],
),
end: BoxDecoration(
color: const Color(0xFFFFFFFF),
border: Border.all(
style: BorderStyle.none,
),
borderRadius: BorderRadius.zero,
// No shadow.
),
);
late AnimationController _controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 3),
)..repeat(reverse: true);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Center(
child: DecoratedBoxTransition(
position: DecorationPosition.background,
decoration: decorationTween.animate(_controller),
child: Container(
width: 200,
height: 200,
padding: const EdgeInsets.all(10),
child: const FlutterLogo(),
),
),
),
);
}
FadeTransition示例
late AnimationController _controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
late Animation _animation = CurvedAnimation(
parent: _controller,
curve: Curves.easeIn,
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: FadeTransition(
opacity: _animation,
child: const Padding(
padding: EdgeInsets.all(8),
child: FlutterLogo()
),
),
);
}
PositionedTransition示例
late AnimationController _controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final double smallLogo = 100;
final double bigLogo = 200;
return LayoutBuilder(
builder: (context, constraints) {
final Size biggest = constraints.biggest;
return Stack(
children: [
PositionedTransition(
rect: RelativeRectTween(
begin: RelativeRect.fromSize(Rect.fromLTWH(0, 0, smallLogo, smallLogo), biggest),
end: RelativeRect.fromSize(Rect.fromLTWH(biggest.width - bigLogo, biggest.height - bigLogo, bigLogo, bigLogo), biggest),
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.elasticInOut,
)),
child: Padding(
padding: const EdgeInsets.all(8),
child: FlutterLogo()
),
),
],
);
},
);
}
RotationTransition示例
late AnimationController _controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
late Animation _animation = CurvedAnimation(
parent: _controller,
curve: Curves.elasticOut,
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RotationTransition(
turns: _animation,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: FlutterLogo(size: 150.0),
),
),
),
);
}
ScaleTransition示例
late AnimationController _controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
late Animation _animation = CurvedAnimation(
parent: _controller,
curve: Curves.fastOutSlowIn,
);
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ScaleTransition(
scale: _animation,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: FlutterLogo(size: 150.0),
),
),
),
);
}
SizeTransition示例
late AnimationController _controller = AnimationController(
duration: const Duration(seconds: 3),
vsync: this,
)..repeat();
late Animation _animation = CurvedAnimation(
parent: _controller,
curve: Curves.fastOutSlowIn,
);
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SizeTransition(
sizeFactor: _animation,
axis: Axis.horizontal,
axisAlignment: -1,
child: Center(
child: FlutterLogo(size: 200.0),
),
),
);
}
SlideTransition示例
class _MyStatefulWidgetState extends State with SingleTickerProviderStateMixin {
late AnimationController _controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
late Animation _offsetAnimation = Tween(
begin: Offset.zero,
end: const Offset(1.5, 0.0),
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.elasticIn,
));
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return SlideTransition(
position: _offsetAnimation,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: FlutterLogo(size: 150.0),
),
);
}
}
不需要外部Animation支持组件示例
AnimatedPadding示例
double padValue = 0.0;
_updatePadding(double value) {
setState(() {
padValue = value;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedPadding(
padding: EdgeInsets.all(padValue),
duration: const Duration(seconds: 2),
curve: Curves.easeInOut,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 5,
color: Colors.blue,
),
),
Text('Padding: $padValue'),
ElevatedButton(
child: Text('Change padding'),
onPressed: () {
_updatePadding(padValue == 0.0 ? 100.0 : 0.0);
}
),
],
);
}
AnimatedPositioned示例
bool selected = false;
@override
Widget build(BuildContext context) {
return Container(
width: 200,
height: 350,
child: Stack(
children: [
AnimatedPositioned(
width: selected ? 200.0 : 50.0,
height: selected ? 50.0 : 200.0,
top: selected ? 50.0 : 150.0,
duration: Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
child: GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Container(
color: Colors.blue,
child: Center(child: Text('Tap me')),
),
),
),
],
),
);
}
AnimatedOpacity示例
class LogoFade extends StatefulWidget {
@override
createState() => LogoFadeState();
}
class LogoFadeState extends State {
double opacityLevel = 1.0;
void _changeOpacity() {
setState(() => opacityLevel = opacityLevel == 0 ? 1.0 : 0.0);
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedOpacity(
opacity: opacityLevel,
duration: Duration(seconds: 3),
child: FlutterLogo(),
),
ElevatedButton(
child: Text('Fade Logo'),
onPressed: _changeOpacity,
),
],
);
}
}
AnimatedAlign示例
bool selected = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Center(
child: Container(
width: 250.0,
height: 250.0,
color: Colors.red,
child: AnimatedAlign(
alignment: selected ? Alignment.topRight : Alignment.bottomLeft,
duration: const Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
child: const FlutterLogo(size: 50.0),
),
),
),
);
}
AnimatedContainer示例
bool selected = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Center(
child: AnimatedContainer(
width: selected ? 200.0 : 100.0,
height: selected ? 100.0 : 200.0,
color: selected ? Colors.red : Colors.blue,
alignment: selected ? Alignment.center : AlignmentDirectional.topCenter,
duration: Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
child: FlutterLogo(size: 75),
),
),
);
}
AnimatedDefaultTextStyle示例
var duration = Duration(seconds: 5);
TextStyle _style = TextStyle(color: Colors.black);
@override
Widget build(BuildContext context) {
return AnimatedDefaultTextStyle(
child: GestureDetector(
child: Text("hello world"),
onTap: () {
setState(() {
_style = TextStyle(
color: Colors.blue,
decorationStyle: TextDecorationStyle.solid,
decorationColor: Colors.blue,
);
});
},
),
style: _style,
duration: duration,
);
}
结语
整体上来说,如果是实现比较简单的动画可以直接使用Flutter内置的动画组件,可以大大减少代码量.本篇文章算是一个记录吧,如果深入,可自行查看下面的参考内容.
欢迎持续关注骚栋,有任何问题欢迎联系骚栋.