【问题标题】:Flutter Checkbox wrong animation inside a ReorderableListView在 ReorderableListView 中颤动 Checkbox 错误动画
【发布时间】:2021-08-01 04:10:39
【问题描述】:

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

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

ReorderableListView(
  padding: const EdgeInsets.symmetric(horizontal: 40),
  children: <Widget>[
    for (int index = 0; index < _items.length; index++)
      ListTile(
        leading: Checkbox(
          
          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

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

【问题讨论】:

  • 我刚刚注意到,如果我使用 GlobalKey() 而不是 Key('$index') 它会保持 Checkbox 状态,但我仍然需要了解发生了什么

标签: flutter checkbox reorderable-list


【解决方案1】:

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

第二,key需要非index-based。您可以使用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,
              value: _items[index].isOdd ? true : false,
            ),
            // here
            key: ValueKey(_items[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);
        });
      },
    );
  }
}

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

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

【讨论】:

  • 嗨,Alex,我刚刚意识到匹配错误
  • 不用担心,如果您认为这个问题对未来的读者可能有价值,我建议您接受答案。
【解决方案2】:

我刚刚意识到我的错误,使用 key: Key('$index') 是错误的,因为它正在改变 onReorder,所以颤振将我旧的选中 Checkbox 值与新的未选中 Checkbox(My bad =|) 匹配。只需在 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]}'),
      ),

【讨论】:

    猜你喜欢
    • 2023-03-04
    • 2020-04-13
    • 2019-11-10
    • 1970-01-01
    • 2019-08-12
    • 2019-01-15
    • 2015-08-16
    • 2019-09-28
    • 1970-01-01
    相关资源
    最近更新 更多