AnimatedList
是一个有状态的 Widget,对应的 State 类型为AnimatedListState
AnimatedList 的结构如下:
const AnimatedList({
Key? key,
required Widget Function(BuildContext, int, Animation<double>) itemBuilder,//数据构造器
int initialItemCount = 0,//初始化的数据的总长度
Axis scrollDirection = Axis.vertical,//滚动方向
bool reverse = false,//是否从下往上显示
ScrollController? controller,//滚动的controller,非必填,控制列表的滚动位置
bool? primary,//是否关联父级滚动
ScrollPhysics? physics,//如何响应用户操作
bool shrinkWrap = false,
EdgeInsetsGeometry? padding,//内边距
Clip clipBehavior = Clip.hardEdge,
})
State 里有两个方法可以添加和删除列表里的元素:
注意,如果 List 绑定了数据源 List 的话,不能直接通过 remove 或者 add 元素达到更新列表的效果,还需要执行下面的方法:
//插入元素
void insertItem(
int index,
{Duration duration = _kDuration}
)
//删除元素
void removeItem(
int index,
Widget Function(BuildContext, Animation<double>) builder, {
Duration duration = _kDuration,
})
添加和删除的时候都会显示指定的动画
使用 insertItem、removeItem 时通常需要配合 globalKey,但 globalKey 需要指定泛型,这样才能调用到增加和删除列表元素的方法:
final globalKey = GlobalKey<AnimatedListState>();
添加元素的时候只需要:
list.add("新增数据");
globalKey.currentState!.insertItem(list.length - 1);
删除元素的时候比较麻烦,因为需要显示元素离开时候的动画然后再删除对应数据源的条目:
一般我们需要建一个
_buildItem
方法来动态创建子元素,执行removeItem
的时候先在回调里面创建一个一摸一样的子元素,如何使用动画淡出,最后删除数据数组中的数据即可.
//删除元素
_delItem(index) {
globalKey.currentState!.removeItem(index, (context, animation) {
//获取要删除的元素,让他淡出显示
var removeItem = _buildItem(index);
return FadeTransition(
//执行动画
opacity: animation,
child: removeItem,
);
});
list.removeAt(index); //删除数组中的数据
}
完整代码#
//AnimatedList
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//定义一个globalKey
final globalKey = GlobalKey<AnimatedListState>();
List<String> list = ["第一条数据", "第二条数据"];
bool flag = true;
Widget _buildItem(index) {
return ListTile(
title: Text(list[index]),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
//执行删除
_delItem(index);
},
),
);
}
//删除元素
_delItem(index) {
globalKey.currentState!.removeItem(index, (context, animation) {
//获取要删除的元素,让他淡出显示
var removeItem = _buildItem(index);
list.removeAt(index); //删除数组中的数据
return FadeTransition(
//执行动画
opacity: animation,
child: removeItem,
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("kano")),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
//这样直接操作list不会对AnimatedList生效
onPressed: () {
// setState(() {
// list.add("新增数据");
// });
///使用AnimatedList中的insertItem方法
list.add("新增数据");
globalKey.currentState!.insertItem(list.length - 1);
},
),
//带有动画的List列表
body: AnimatedList(
key: globalKey,
initialItemCount: list.length,
itemBuilder: (context, index, animation) {
//fade过渡 opacity 进入从0到1 离开则相反
return FadeTransition(opacity: animation);
//scale过渡
// return ScaleTransition(scale: animation);
},
),
);
}
}