simple_animations简化了创建精美自定义动画的过程:
- 在无状态小部件中轻松创建自定义动画
- 一次为多个属性设置动画
- 在几秒钟内创建交错动画
- 简化了AnimationController实例的使用
- 调试动画
快速开始
Animation Builder
通过Animation Builder可以轻松创建自定义动画。
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';
class ResizeCubeAnimation extends StatelessWidget {
const ResizeCubeAnimation({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// PlayAnimationBuilder plays animation once
return PlayAnimationBuilder<double>(
tween: Tween(begin: 100.0, end: 200.0), // 100.0 to 200.0
duration: const Duration(seconds: 1), // for 1 second
builder: (context, value, _) {
return Container(
width: value, // use animated value
height: value,
color: Colors.blue,
);
},
onCompleted: () {
// do something ...
},
);
}
}
class RotatingBox extends StatelessWidget {
const RotatingBox({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// LoopAnimationBuilder plays forever: from beginning to end
return LoopAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 2 * pi), // 0° to 360° (2π)
duration: const Duration(seconds: 2), // for 2 seconds per iteration
builder: (context, value, _) {
return Transform.rotate(
angle: value, // use value
child: Container(color: Colors.blue, width: 100, height: 100),
);
},
);
}
}
class ColorFadeLoop extends StatelessWidget {
const ColorFadeLoop({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// MirrorAnimationBuilder plays forever: alternating forward and backward
return MirrorAnimationBuilder<Color?>(
tween: ColorTween(begin: Colors.red, end: Colors.blue), // red to blue
duration: const Duration(seconds: 5), // for 5 seconds per iteration
builder: (context, value, _) {
return Container(
color: value, // use animated value
width: 100,
height: 100,
);
},
);
}
}
MovieTween
MovieTween可以将多个Tween合并成一个,包括时间线控制和值外推。
import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';
// Simple staggered tween
final tween1 = MovieTween()
..tween('width', Tween(begin: 0.0, end: 100),
duration: const Duration(milliseconds: 1500), curve: Curves.easeIn)
.thenTween('width', Tween(begin: 100, end: 200),
duration: const Duration(milliseconds: 750), curve: Curves.easeOut);
// Design tween by composing scenes
final tween2 = MovieTween()
..scene(
begin: const Duration(milliseconds: 0),
duration: const Duration(milliseconds: 500))
.tween('width', Tween<double>(begin: 0.0, end: 400.0))
.tween('height', Tween<double>(begin: 500.0, end: 200.0))
.tween('color', ColorTween(begin: Colors.red, end: Colors.blue))
..scene(
begin: const Duration(milliseconds: 700),
end: const Duration(milliseconds: 1200))
.tween('width', Tween<double>(begin: 400.0, end: 500.0));
// Type-safe alternative
final width = MovieTweenProperty<double>();
final color = MovieTweenProperty<Color?>();
final tween3 = MovieTween()
..tween<double>(width, Tween(begin: 0.0, end: 100))
..tween<Color?>(color, ColorTween(begin: Colors.red, end: Colors.blue));
AnimationMixin
用AnimationMixin管理AnimationController,不再需要实现复杂的样板代码。
import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';
class MyWidget extends StatefulWidget {
const MyWidget({Key? key}) : super(key: key);
@override
_MyWidgetState createState() => _MyWidgetState();
}
// Add AnimationMixin
class _MyWidgetState extends State<MyWidget> with AnimationMixin {
late Animation<double> size;
@override
void initState() {
// The AnimationController instance `controller` is already wired up.
// Just connect with it with the tweens.
size = Tween<double>(begin: 0.0, end: 200.0).animate(controller);
controller.play(); // start the animation playback
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
width: size.value, // use animated value
height: size.value,
color: Colors.red,
);
}
}
Animation Developer Tools(调试工具)
Animation Developer Tools可以帮助开发者逐步创建或检查动画。非常好用。
import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';
void main() => runApp(const MaterialApp(home: Scaffold(body: MyPage())));
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SafeArea(
// put DevTools very high in the widget hierarchy
child: AnimationDeveloperTools(
child: Center(
child: PlayAnimationBuilder<double>(
tween: Tween<double>(begin: 0.0, end: 100.0),
duration: const Duration(seconds: 1),
developerMode: true, // enable developer mode
builder: (context, value, child) {
return Container(
width: value,
height: value,
color: Colors.blue,
);
},
),
),
),
);
}
}