banner
MiniKano

MiniKano

This is MiniKano's blog based on Blockchain technology. 新手,请多关照~
github

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

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

效果图#

1-3[1].gif

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。