5. 动画
5.1 AnimatedList
一个滚动容器,可以为item被插入或移除时添加动画效果。列表数据的插入和删除有进出场动画需要调用AnimatedListState指定的方法,只删除原数据并调用setState方法是没有动画效果的。nimatedListState.insertItem或AnimatedListState.removeItem并不会更新实际数据,需要手动处理。
import 'dart:async';
import 'package:flutter/material.dart';
class Search extends StatefulWidget {
final Map arguments;
const Search({super.key, required this.arguments});
@override
State createState() => _SearchState();
}
class _SearchState extends State {
// 1、新增key
final globalKey = GlobalKey();
List list = ["第一条数据", "第二条数据"];
// 设置flag,防止快速点击删除,导致的bug
var flag = true;
// 删除一行数据
_deleteItem(index) {
if (flag) {
flag = false;
globalKey.currentState!.removeItem(index, (context, animation) {
var removeItem = _buildItem(index);
list.removeAt(index);
return FadeTransition(
opacity: animation,
// 删除时,执行动画的元素
child: removeItem,
);
});
Timer.periodic(Duration(milliseconds: 600), (timer) {
flag = true;
timer.cancel();
});
}
}
Widget _buildItem(index) {
return ListTile(
title: Text(list[index]),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: (() {
_deleteItem(index);
}),
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.arguments["title"]),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
list.add("我是新怎数据${list.length + 1}");
// 3、增加一行的动画
globalKey.currentState!.insertItem(list.length - 1);
},
),
body: AnimatedList(
// 2、设置key
key: globalKey,
initialItemCount: list.length,
itemBuilder: ((context, index, animation) {
return FadeTransition(opacity: animation, child: _buildItem(index));
}),
));
}
}
5.2 隐式(全自动)动画
所谓隐式动画就是只需要设置动画目标,过程控制由系统实现
一般是简单点的动画,比如只是简单的宽高变化。
AnimatedContainer:宽,高,位移
AnimatedPadding:设置间距
AnimatedOpacity:透明度
AnimatedPositioned:方位top,left,right,bottom
AnimatedDefaultTextStyle:文字样式
AnimatedSwitcher:子元素改变时,执行的动画,不同控件间切换的过渡动画
import 'package:flutter/material.dart';
class AnimationPage extends StatefulWidget {
const AnimationPage({super.key});
@override
State createState() => _AnimationPageState();
}
class _AnimationPageState extends State {
var _flag = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("动画"),
),
floatingActionButton: FloatingActionButton(
onPressed: (() {
setState(() {
_flag = !_flag;
});
}),
child: const Icon(Icons.add),
),
body: Center(
child: AnimatedContainer(
// 动画时间
duration: const Duration(milliseconds: 600),
// 动画线性类型
curve: Curves.bounceIn,
width: _flag ? 100 : 150,
height: _flag ? 100 : 150,
transform: _flag
? Matrix4.translationValues(100, 0, 0)
: Matrix4.translationValues(0, 0, 0),
color: Colors.red,
),
),
);
}
}
5.3 Hero动画
hero动画有个特点,就是触发那一刻就变为目标ui然后开始动画
功能强大,使用简单,只需要在开始和目标ui上包括Hero并设置相同唯一的tag即可
- Hero指的是可以在路由(页面)之间“飞行”的widget。
- 使用Flutter的Hero widget创建hero动画。
- 将 hero从一个路由飞到另一个路由。
- 将 hero 的形状从圆形转换为矩形,同时将其从一个路由飞到另一个路由的过程中进行动画处理。
- Flutter中的Hero widget实现了通常称为 共享元素转换 或 共享元素动画的动画风格。
详细参考:https://blog.51cto.com/liyuanjinglyj/5016276