使用AnimatedList实现列表项目增加和删除

AnimatedList是一个有状态的 Widget，对应的 State 类型为AnimatedListState

AnimatedList 的结构如下：

Copy
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 元素达到更新列表的效果，还需要执行下面的方法：

Copy
//插入元素
void insertItem(
int index,
{Duration duration = _kDuration}
)
//删除元素
void removeItem(
int index,
Widget Function(BuildContext, Animation<double>) builder, {
Duration duration = _kDuration,
})

添加和删除的时候都会显示指定的动画

使用 insertItem、removeItem 时通常需要配合 globalKey，但 globalKey 需要指定泛型，这样才能调用到增加和删除列表元素的方法：

Copy
final globalKey = GlobalKey<AnimatedListState>();

添加元素的时候只需要：

Copy
list.add("新增数据");
globalKey.currentState!.insertItem(list.length - 1);

删除元素的时候比较麻烦，因为需要显示元素离开时候的动画然后再删除对应数据源的条目:

一般我们需要建一个_buildItem方法来动态创建子元素，执行removeItem的时候先在回调里面创建一个一摸一样的子元素，如何使用动画淡出，最后删除数据数组中的数据即可.

Copy
//删除元素
_delItem(index) {
globalKey.currentState!.removeItem(index, (context, animation) {
//获取要删除的元素，让他淡出显示
var removeItem = _buildItem(index);
return FadeTransition(
//执行动画
opacity: animation,
child: removeItem,
);
});
list.removeAt(index); //删除数组中的数据
}

完整代码

Copy
//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);
},
),
);
}
}

效果图