ReorderableListView 中的 Flutter Checkbox 错误动画

问题描述

我一定做错了什么,但是当我在 ReorderableListView 中重新排列选中的复选框时,它正在为未选中的磁贴设置动画:

enter image description here

这是我正在使用的示例代码

ReorderableListView(
  padding: const EdgeInsets.symmetric(horizontal: 40),children: <Widget>[
    for (int index = 0; index < _items.length; index++)
      ListTile(
        leading: Check@R_502_6277@(
          
          key: Key('$index'),onChanged: (v) => null,value: _items[index].isOdd ? true : false,),key: Key('$index'),tileColor: _items[index].isOdd ? oddItemColor : evenItemColor,title: Text('Item ${_items[index]}'),],onReorder: (int oldindex,int newIndex) {
    setState(() {
      if (oldindex < newIndex) {
        newIndex -= 1;
      }
      final int item = _items.removeAt(oldindex);
      _items.insert(newIndex,item);
    });

完整的code here

我怎样才能正确地做到这一点? 干杯!

解决方法

我刚刚意识到我的错误,使用 key: Key('$index') 是错误的,因为它正在更改 onReorder,所以 flutter 将我的旧选中的 Checkbox 值与新的未选中的 Checkbox 匹配(我的错误 =|)。只需在 ListTile 中使用 ObjectKey,它就会正确匹配!

ListTile(
        leading: Checkbox(
          onChanged: (v) => null,value: _items[index].isOdd ? true : false,),key: ObjectKey(_items[index]),tileColor: _items[index].isOdd ? oddItemColor : evenItemColor,title: Text('Item ${_items[index]}'),
,

首先,您只需要 ListTile 上的键,因为它们是 ReorderableListView 的直接后代。

其次,key需要非索引型。您可以使用 UniqueKeyGlobalKey,但最佳做法是使用 ValueKey,在该索引处传递值。

就你而言:

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  final List<int> _items = List<int>.generate(2,(int index) => index);

  @override
  Widget build(BuildContext context) {
    return ReorderableListView(
      padding: const EdgeInsets.symmetric(horizontal: 40),children: <Widget>[
        for (int index = 0; index < _items.length; index++)
          ListTile(
            leading: Checkbox(
              onChanged: (v) => null,// here
            key: ValueKey(_items[index]),],onReorder: (int oldIndex,int newIndex) {
        setState(() {
          if (oldIndex < newIndex) {
            newIndex -= 1;
          }
          final int item = _items.removeAt(oldIndex);
          _items.insert(newIndex,item);
        });
      },);
  }
}

至于为什么您的索引键不起作用 - 我的理解是在小部件重建后(通过重新排序列表),您的 ListTile 被键入错误的索引(因为该 {{1 }} 已经改变)。当您使用该值时,它是一个可用于标识小部件的常量。

Emily Fortuna 在 Medium 上写了一篇关于键的 wonderful article,如果您打算继续使用 Flutter 进行开发,我强烈建议您阅读。