我正在 Flutter 中创建一个表单(不使用
Form
小部件),用户可以在其中添加任意数量的项目(处理),这些项目在 InputChip
小部件中呈现为 Wrap
小部件列表。
该表单使用一个按钮(
AddButton
小部件)来打开一个表单对话框,该对话框本身返回添加到 selectedItems: 的新创建的项目(处理)
class TreatmentsWidget extends StatefulWidget {
const TreatmentsWidget({super.key, required this.selectedItems});
final List<Treatment> selectedItems;
@override
State<TreatmentsWidget> createState() => _TreatmentsWidgetState();
}
class _TreatmentsWidgetState extends State<TreatmentsWidget> {
@override
Widget build(BuildContext context) {
var chips = widget.selectedItems.map(
(item) {
return InputChip(
label: Text('${item.name} - ${item.frequency}/${item.frequencyUnit.name})',
);
},
).toList();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
children: chips,
),
AddButton(onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const TreatmentDialog();
}).then((value) {
if (value != null) {
Treatment item = value;
setState(() {
widget.selectedItems.add(item);
});
}
});
}),
],
);
}
}
由于某种原因,当将新项目添加到 selectedItem 并且该项目溢出当前行时,不会重新计算布局,从而导致
Wrap
小部件溢出按钮:
但是,一旦用户滚动(整个屏幕内容都在
SingleChildScrollView
内),布局就会重新计算,并且 Wrap
会占用正确的空间量:
添加新项目时如何强制重画以防止出现此故障?
问题似乎是,当
Column
的一个子尺寸发生变化时,它不会在当前帧上重新计算其尺寸。
每当
Column
发生变化时,我最终都会强制使用 ValueKey
重建 chips.length
:
class _TreatmentsWidgetState extends State<TreatmentsWidget> {
@override
Widget build(BuildContext context) {
var chips = ...;
return Column(
key: ValueKey(chips.length),
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
children: chips,
),
AddButton(...),
],
);
}
}
我仍然对更清洁的解决方案感兴趣(如果存在)。对于这种情况,使用提供商似乎有些过分了。
我遇到了与您的问题中描述的类似的问题,它源于 Ink 小部件。我无法调查为什么会出现这种行为。您遇到此问题是否可能是因为 Wrap 内代码中的某处存在 Ink 小部件?
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
OtherWidget(),
Expanded(
child: SingleChildScrollView(
child: Wrap(
spacing: 8 * 2,
runSpacing: 8 * 2,
clipBehavior: Clip.antiAlias,
children: [
Ink(),
Ink(),
Ink(),
Ink(),
Ink(),
Ink(),
Ink(),
Ink(),
Ink(),
],
),
),
),
SomeOtherWidget(),
],
);
}
}
我刚刚用 Container() 替换了 Ink()。
PD:希望这有帮助