1. Introduction to AnimatedWidget
The AnimatedWidget base class separates core widget code from animation code. AnimatedWidget doesn't need to keep State object to hold animation. AnimatedWidget helper class (instead of addListener() and setState()) to create animated widgets.
Use AnimatedWidget to create a widget that can run reusable animations.
AnimatedWidget in Flutter API: AnimatedBuilder, RotationTransition, ScaleTransition, SizeTransition, SlideTransition.
Two, AnimatedWidget animation example
One shrinks from the width and height of the rectangle
class MyAnimationWidget extends StatefulWidget {
const MyAnimationWidget({
Key? key}) : super(key: key);
@override
_MyAnimationWidgetState createState() => _MyAnimationWidgetState();
}
class _MyAnimationWidgetState extends State<MyAnimationWidget>
with SingleTickerProviderStateMixin {
late AnimationController controller;
late Animation<double> animation;
@override
initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = Tween(begin: 0.0, end: 300.0).animate(controller);
controller.forward();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: AnimationLogo(animation),
),
);
}
}
class AnimationLogo extends AnimatedWidget {
const AnimatedLogo({
super.key, required Animation<double> animation})
: super(listenable: animation);
@override
Widget build(BuildContext context) {
final animation = listenable as Animation<double>;
return Center(
child: Container(
height: animation.value,
width: animation.value,
color: Colors.red,
),
);
}
}
3. Refactoring with AnimatedBuilder
AnimatedBuilder knows how to render transitions
But AnimatedBuilder does not render widgets, nor does it control animated objects.
Use AnimatedBuilder to describe an animation as part of other widget build methods. If you simply need to define a widget with reusable animations.
Flutter API 中 AnimatedBuilders:BottomSheet, ExpansionTile, PopupMenu, ProgressIndicator, RefreshIndicator, Scaffold, SnackBar, TabBar, TextField。
One problem with the AnimatedWidget sample code is that changing the animation requires changing the widget that renders the logo. A better solution is to separate tasks into different classes:
a. Render the logo
b. Define animation objects
c. Render transition effects
AnimatedBuilder animation example
class _MyAnimationWidgetState extends State<MyAnimationWidget>
with SingleTickerProviderStateMixin {
late AnimationController controller;
late Animation<double> animation;
@override
initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = Tween(begin: 0.0, end: 300.0).animate(controller);
controller.forward();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: AnimationLogo(
animation,
child: LogoWidget(),
),
),
);
}
}
class LogoWidget extends StatelessWidget {
const LogoWidget({
Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Container(
color: Colors.red,
),
);
}
}
class AnimationLogo extends StatelessWidget {
final Animation<double> animation;
final Widget child;
AnimationLogo(this.animation, {
Key? key, required this.child});
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget? child) {
return SizedBox(
height: animation.value,
width: animation.value,
child: child,
);
},
child: child,
);
}
}
Four. Summary
From the above code, we can see that the widget and the animation effect are separated, so AnimatedBuilder further separates the AnimatedWidget, so that the animation effect can be reused, which is very good.