AnimatedList 实现动态列表

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常见属性:


关于GlobalKey: 每个 Widget 都对应一个 Element ,我们可以直接对 Widget 进行操作,但是无法直
接操作 Widget 对应的 Element 。而 GlobalKey 就是那把直接访问 Element 的钥匙。通过 GlobalKey
可以获取到 Widget 对应的 Element 。

AnimatedList增加列表FadeTransition、ScaleTransition

FadeTransition Demo
复制代码
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final globalKey = GlobalKey<AnimatedListState>();
  List<String> list = ["第一条数据", "第二条数据"];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            list.add("这是一个新增数据");
            globalKey.currentState!.insertItem(list.length - 1); //索引值为n-1
          });
        },
        child: Icon(Icons.abc),
      ),
      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
复制代码
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final globalKey = GlobalKey<AnimatedListState>();
  List<String> list = ["第一条数据", "第二条数据"];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            list.add("这是一个新增数据");
            globalKey.currentState!.insertItem(list.length - 1); //索引值为n-1
          });
        },
        child: Icon(Icons.abc),
      ),
      body: AnimatedList(
          key: globalKey,
          initialItemCount: list.length,
          itemBuilder: (context, index, animation) {
            return ScaleTransition(
              scale: animation,
              child: ListTile(
                  title: Text(list[index]), trailing: Icon(Icons.delete)),
            );
          }),
    );
  }
}

AnimatedList 删除列表

复制代码
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final globalKey = GlobalKey<AnimatedListState>();
  bool flag = true;
  List<String> list = ["第一条数据", "第二条数据"];

//删除
  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, //执行动画的元素
            );
          },
        );
      });
//解决快速删除bug 重置flag
      const timeout = Duration(milliseconds: 2000); //每2秒才删除一个
      Timer.periodic(timeout, (timer) {
        flag = true;
        timer.cancel();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            list.add("这是一个新增数据");
            globalKey.currentState!.insertItem(list.length - 1); //索引值为n-1
          });
        },
        child: const Icon(Icons.abc),
      ),
      body: AnimatedList(
          key: globalKey,
          initialItemCount: list.length,
          itemBuilder: (context, index, animation) {
            return ScaleTransition(
              scale: animation,
              child: _buildItem(context, index),
            );
          }),
    );
  }
}