我正在使用 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。
我错过了什么吗?这是这个小部件的默认行为吗?
您无需手动跟踪正在拖动的子项来自定义其外观。
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
文档。