ReordableListView.builder 无法使用 itemBuilder 的动态参数

问题描述 投票:0回答:1

我正在使用 ReordableListView 呈现可订购的 MemoItem 小部件列表。

我的设置与列表配合得很好,但我需要向渲染的小部件添加自定义,这样如果 MemoItem 被“选择”(正在拖动),它将在 ui 中发生一些变化(如不同的边框)。

我试图做的是将 selectedIndex 置于状态中并使用 onReoderStart 和 onReorderEnd 进行更新。我打印了所有可以打印的内容并且它正在工作,但是由于某种原因,ReordableListView 构建器没有将正确的值传递给小部件。输入小部件时 isSelected 为 true,但如果我在小部件内打印它,则为 false。

这就像小部件是恒定的,并且当参数改变时不会重建。当然,当我拖动项目时,树正在重建,但构建器内的项目保持“不变”。

我检查过密钥是唯一的。

这是我的代码(编辑了不相关的部分):

class MemoPage extends ConsumerStatefulWidget {
  const MemoPage({super.key});

  @override
  ConsumerState<MemoPage> createState() => _MemoPageState();
}

class _MemoPageState extends ConsumerState<MemoPage> {
  int? selectedIndex;


  @override
  Widget build(BuildContext context) {
    final allMemo = ref.watch(memoListProvider.select((state) => state.allMemos));
    ref.watch(memoListProvider);
    final bool isMemoListEmpty = allMemo.isEmpty;
    final bool isLoading = ref.watch(memoListProvider.select((state) => state.isLoading));

  

    return Scaffold(
      backgroundColor: CustomColors.lightGrey,
      body: Builder(builder: (context) {
        return ReorderableListView.builder(
            itemCount: allMemo.length,
            itemBuilder: (context, index) {
              bool isSelected = selectedIndex == index;
              if (isSelected) {
                print('selected index: $index');
                
            // It is correctly printing selected index = n when the widget is selected
              }
              return MemoItem(
                key: ValueKey('${allMemo[index].id}'),
                memo: allMemo[index],
            
            // It is not correctly passing the value of isSelected to the MemoItem widget. 
            // If I print isSelected inside the MemoItem widget, it's always returning 
            // false.

                isSelected: isSelected,
              );
            },
            
            onReorderEnd: (index) {
              selectedIndex = null;
            },
            onReorderStart: (index) {
              selectedIndex = index;
            },
            
      }),
    );
  }

}

在我的 MemoItemWidget 中(为简单起见进行了编辑)

class MemoItem extends StatelessWidget {
  const MemoItem({super.key, required this.isSelected, required this.memo});
    // memo object
  final bool isSelected;
  @override
  Widget build(BuildContext context) {
    print(isSelected);
    return const SizedBox();
  }
}

isSelected 始终打印 false。

我错过了什么吗?这是这个小部件的默认行为吗?

flutter dart mobile-development
1个回答
0
投票

您无需手动跟踪正在拖动的子项来自定义其外观。

ReorderableListView.builder
有一个内置回调
proxyDecorator
,它允许您将自定义 UI 更改(如边框)应用于正在拖动的小部件。

例如,如果您想在拖动的项目周围添加实心红色边框,您可以这样做:

proxyDecorator: (widget, index, animation) {
  return Material(
    type: MaterialType.transparency,
    child: DecoratedBox(
      decoration: BoxDecoration(
        border: Border.all(
          width: 2,
          color: Colors.red,
        ),
      ),
      child: widget,
    ),
  );
}

有关更多示例和详细信息,请查看

ReorderableListView
文档

© www.soinside.com 2019 - 2024. All rights reserved.