最近写了一些flutter的小动画,在这里也写几个篇章介绍下flutter的动画的实现,先实现个简单的帧动画,举例美团的加载动画就是帧动画的实现,那换flutter的怎么实现呢,一起看看
主要的类实现FrameAnimationImage
class FrameAnimationImage extends StatefulWidget {
final List<String> _assetList;
final double width;
final double height;
bool start = true;
int interval = 200;
FrameAnimationImage(Key key, this._assetList,
{this.width, this.height, this.interval, this.start})
: super(key: key);
@override
State<StatefulWidget> createState() {
return FrameAnimationImageState();
}
}
class FrameAnimationImageState extends State<FrameAnimationImage>
with SingleTickerProviderStateMixin {
// 动画控制
Animation<double> _animation;
AnimationController _controller;
int interval = 200;
@override
void initState() {
super.initState();
if (widget.interval != null) {
interval = widget.interval;
}
final int imageCount = widget._assetList.length;
final int maxTime = interval * imageCount;
// 启动动画controller
_controller = new AnimationController(
duration: Duration(milliseconds: maxTime), vsync: this);
_controller.addStatusListener((AnimationStatus status) {
if (status == AnimationStatus.completed) {
_controller.forward(from: 0.0); // 完成后重新开始
}
});
_animation = new Tween<double>(begin: 0, end: imageCount.toDouble())
.animate(_controller)
..addListener(() {
setState(() {
// the state that has changed here is the animation object’s value
});
});
if (widget.start) {
_controller.forward();
}
}
void startAnimation() => _controller.forward();
void stopAnimation() => _controller.stop();
void reStartAnimation(){
_controller.reset();
_controller.forward();
}
@override
void didUpdateWidget(FrameAnimationImage oldWidget) {
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
print("didUpdateWidget called");
if (widget.start) {
_controller.forward();
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
int ix = _animation.value.floor() % widget._assetList.length;
List<Widget> images = [];
// 把所有图片都加载进内容,否则每一帧加载时会卡顿
for (int i = 0; i < widget._assetList.length; ++i) {
if (i != ix) {
images.add(Image.asset(
ImageUtils.getImagePath( widget._assetList[i]),///ImageUtils只是一个简单出来图片格式的方法
width: 0,
height: 0,
));
}
}
images.add(Image.asset(
ImageUtils.getImagePath(widget._assetList[ix]),//
width: widget.width,
height: widget.height,
));
return Stack(alignment: AlignmentDirectional.center, children: images);
}
}
//class ImageUtils {
// static String getImagePath(String name, {String format: 'png'}) {
// return 'assets/images/$name.$format';
// }
//
// static ImageProvider getImageProvider(String imageUrl,
// {String holderImg: "none"}) {
// if (TextUtil.isEmpty(imageUrl)) {
// return AssetImage(getImagePath(holderImg));
// }
// return CachedNetworkImageProvider(imageUrl);
// }
//}
这个类的实现也比较好理解的,通过监听AnimationStatus 动画的状态,对动画实现控制。下面看下实现示例.
准备好图片:
class Frame extends StatelessWidget {
bool b = false;
final List<String> list = [
'go1',
'go2',
'go3',
'go4',
];
final GlobalKey<FrameAnimationImageState> _cotroller = new GlobalKey<FrameAnimationImageState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('帧动画'),
centerTitle: true,
),
body: Column(
children: <Widget>[
Center(
child: GestureDetector(
onTap: () {
if (b) {
_cotroller.currentState.reStartAnimation();
} else {
_cotroller.currentState.startAnimation();
}
b = !b;
},
child: FrameAnimationImage(_cotroller, list,
width: 220, height: 200, interval: 50, start: false),
),
),
RaisedButton(
onPressed: (){
_cotroller.currentState.stopAnimation();
},
child: Text("结束"),
)
],
)
);
}
}
将图片上去,运行、就可以看见小鹿跑动的动画啦。
很简单是不是,帧动画就这样吧,要是控制时间什么的自己添加修改就好了,还有注意帧动画图片的大小喔。