Flutter AnimatedList 实现动态列表
Flutter AnimatedList 实现动态列表视频教程 :https://www.bilibili.com/video/BV1S4411E7LY?p=46
一、 AnimatedList实现动画
AnimatedList 和 ListView 的功能大体相似,不同的是, AnimatedList 可以在列表中插入或删除节点时执行一个动画,在需要添加或删除列表项的场景中会提高用户体验。
AnimatedList 是一个 StatefulWidget,它对应的 State 类型为 AnimatedListState,添加和删除元素的方法位于 AnimatedListState 中:
void insertItem(int index, { Duration duration = _kDuration });
void removeItem(int index, AnimatedListRemovedItemBuilder builder, { Duration duration = _kDuration }) ;
AnimatedList常见属性:
属性 | 描述 |
---|---|
key | globalKey final globalKey = GlobalKey<AnimatedListState>(); |
initialItemCount | 子元素数量 |
itemBuilder | 方法 ( BuildContext context, int index, Animation<double> animation) {} |
关于GlobalKey: 每个Widget
都对应一个Element
,我们可以直接对Widget
进行操作,但是无法直接操作Widget
对应的Element
。而GlobalKey
就是那把直接访问Element
的钥匙。通过GlobalKey
可以获取到Widget
对应的Element
。
二、 AnimatedList增加列表FadeTransition、ScaleTransition
FadeTransition Demo
import 'package:flutter/material.dart';
class AnimatedListPage extends StatefulWidget {
const AnimatedListPage({super.key});
@override
State<AnimatedListPage> createState() => _AnimatedListPageState();
}
class _AnimatedListPageState extends State<AnimatedListPage> {
final globalKey = GlobalKey<AnimatedListState>();
List<String> list = ["第一条数据","第二条数据"];
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: (){
list.add("这是一个数据");
globalKey.currentState!.insertItem(list.length - 1);
},
child: const Icon(Icons.add),
),
appBar: AppBar(
title: const Text("AppBar组件"),
),
body: AnimatedList(
key: globalKey,
initialItemCount: list.length,
itemBuilder: (context, index, animation) {
return FadeTransition(
opacity: animation,
child: ListTile(
title: Text(list[index]),
trailing: Icon(Icons.delete)
),
);
}),
);
}
}
ScaleTransition demo
import 'package:flutter/material.dart';
class AnimatedListPage extends StatefulWidget {
const AnimatedListPage({super.key});
@override
State<AnimatedListPage> createState() => _AnimatedListPageState();
}
class _AnimatedListPageState extends State<AnimatedListPage> {
final globalKey = GlobalKey<AnimatedListState>();
List<String> list = ["第一条数据","第二条数据"];
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: (){
list.add("这是一个数据");
globalKey.currentState!.insertItem(list.length - 1);
},
child: const Icon(Icons.add),
),
appBar: AppBar(
title: const Text("AppBar组件"),
),
body: AnimatedList(
key: globalKey,
initialItemCount: list.length,
itemBuilder: (context, index, animation) {
print(animation);
return ScaleTransition(
scale: animation,
child: ListTile(
title: Text(list[index]),
trailing: Icon(Icons.delete)
),
);
}),
);
}
}
三、 AnimatedList 删除列表
import 'dart:async';
import 'package:flutter/material.dart';
class AnimatedListPage extends StatefulWidget {
const AnimatedListPage({super.key});
@override
State<AnimatedListPage> createState() => _AnimatedListPageState();
}
class _AnimatedListPageState extends State<AnimatedListPage> {
final globalKey = GlobalKey<AnimatedListState>();
bool flag = true;
List<String> list = ["第一条数据", "第二条数据"];
@override
void initState() {
// TODO: implement initState
super.initState();
}
Widget _buildItem(context, index) {
return ListTile(
key: ValueKey(index),
title: Text(list[index]),
trailing: IconButton(
icon: Icon(Icons.delete),
// 点击时删除
onPressed: () => _deleteItem(context, index),
));
}
_deleteItem(context, index) {
if (flag == true) {
flag = false;
print(index);
//注意:删除后需要重新setState
setState(() {
// 删除过程执行的是反向动画,animation.value 会从1变为0
globalKey.currentState!.removeItem(index, (context, animation) {
//注意先build然后再去删除
var item = _buildItem(context, index);
list.removeAt(index);
return FadeTransition(
opacity: animation,
child: item,
);
},duration: Duration(milliseconds: 500));
});
//解决快速删除bug 重置flag
const timeout = Duration(milliseconds: 600);
Timer.periodic(timeout, (timer) {
flag=true;
timer.cancel();
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
// 增加 animation.value 会从0变为1
list.add("这是一个数据");
globalKey.currentState!.insertItem(list.length - 1);
},
child: const Icon(Icons.add),
),
appBar: AppBar(
title: const Text("AppBar组件"),
),
body: AnimatedList(
key: globalKey,
initialItemCount: list.length,
itemBuilder: (context, index, animation) {
return FadeTransition(
opacity: animation,
child: _buildItem(context, index),
);
}),
);
}
}