如何在 ListView 的顶部插入小部件?
How do I insert widgets at the top of a ListView?
简要说明:
在我所有的代码示例中,您会看到 material.Widget
而不仅仅是 Widget
。这是因为我喜欢这样命名我的导入,例如:
import 'package:flutter/material.dart' as material;
我的问题:
我正在尝试让 ListView 在列表顶部显示新添加的小部件。我有一个简单的有状态小部件,它只包含一个模型列表(类,其中包含构建进入 ListView 的小部件的必要信息),并且应该根据该列表构建 ListView 的子项。
class Page extends material.StatefulWidget {
final List<CardModel> cardModels;
Page(this.cardModels);
@override
_PageState createState() => new _PageState(cardModels);
}
class _PageState extends material.State<Page> {
List<CardModel> cardModels;
_PageState(this.cardModels);
@override
material.Widget build(material.BuildContext context) {
return new material.ListView(
children: cardModels.map((cardModel) => new Card(cardModel.cardID)).toList(),
);
}
}
我期望的行为是,无论何时调用构建方法(并且正确使用了 setState),ListView 都应该被正确地重建,并按照列表的顺序包含子窗口小部件。如果我简单地按顺序向 cardModels 添加新模型,它会成功地做到这一点:
cardModels.add(new CardModel(nextID++));
您可以看到小部件按顺序添加,其 id 正确递增:
但是,我希望在顶部插入较新的小部件(在顶部显示更高的 ID)。为了做到这一点,我尝试在列表的开头插入新模型:
cardModels.insert(0, new CardModel(nextID++));
不幸的是,我没有看到正确的小部件,而是一遍又一遍地看到 ID 为 0 的小部件:
我知道模型列表正在正确更新,因为我可以将其打印出来并按降序查看 ID。我假设有一些关于 flutter 如何检测到导致这种行为的小部件的变化,但在大量阅读之后,我仍然无法弄清楚。任何帮助将非常感激。此外,我在最终构建页面(包含 ListView 的小部件)的小部件中调用设置状态作为其子项之一:
btn = new FloatingActionButton(
onPressed: () => setState(_pageController.addCard),
tooltip: 'Upload File',
child: new Icon(Icons.file_upload),
);
_pageController 是修改模型列表的对象。如果这还不够,请告诉我,我很乐意提供更多代码或回答任何问题。
在 FloatingActionButton
上更改函数以插入新项目然后调用 setState
如:
cardModels.insert(0, new CardModel(nextId++)) ;
setState(() {
cardModels = cardModels;
});
希望对您有所帮助!
事实证明,我制作的 Card 小部件不需要是有状态的。我将其更改为无状态并解决了问题。不知道为什么让它们有状态会破坏它。
有一个简单的快速修复方法,使用 didWidgetUpdate
覆盖,
通过检查 oldWidget
中的 cardModels 对象是否与作为参数传递的 cardModels 相同。
像这样
@override
void didUpdateWidget(covariant Page oldWidget) {
if (widget.cardModels != oldWidget.cardModels) {
setState((){
cardModels = widget.cardModels;
});
}
super.didUpdateWidget(oldWidget);
}
完整示例如下
class Page extends material.StatefulWidget {
final List<CardModel> cardModels;
Page(this.cardModels);
@override
_PageState createState() => new _PageState(cardModels);
}
class _PageState extends material.State<Page> {
List<CardModel> cardModels;
@override
void initState(){
cardModels = widget.cardModels;
super.initState();
}
@override
void didUpdateWidget(covariant Page oldWidget) {
if (widget.cardModels != oldWidget.cardModels) {
setState((){
cardModels = widget.cardModels;
});
}
super.didUpdateWidget(oldWidget);
}
_PageState(this.cardModels);
@override
material.Widget build(material.BuildContext context) {
return new material.ListView(
children: cardModels.map((cardModel) => new Card(cardModel.cardID)).toList(),
);
}
}
简要说明:
在我所有的代码示例中,您会看到 material.Widget
而不仅仅是 Widget
。这是因为我喜欢这样命名我的导入,例如:
import 'package:flutter/material.dart' as material;
我的问题:
我正在尝试让 ListView 在列表顶部显示新添加的小部件。我有一个简单的有状态小部件,它只包含一个模型列表(类,其中包含构建进入 ListView 的小部件的必要信息),并且应该根据该列表构建 ListView 的子项。
class Page extends material.StatefulWidget {
final List<CardModel> cardModels;
Page(this.cardModels);
@override
_PageState createState() => new _PageState(cardModels);
}
class _PageState extends material.State<Page> {
List<CardModel> cardModels;
_PageState(this.cardModels);
@override
material.Widget build(material.BuildContext context) {
return new material.ListView(
children: cardModels.map((cardModel) => new Card(cardModel.cardID)).toList(),
);
}
}
我期望的行为是,无论何时调用构建方法(并且正确使用了 setState),ListView 都应该被正确地重建,并按照列表的顺序包含子窗口小部件。如果我简单地按顺序向 cardModels 添加新模型,它会成功地做到这一点:
cardModels.add(new CardModel(nextID++));
您可以看到小部件按顺序添加,其 id 正确递增:
但是,我希望在顶部插入较新的小部件(在顶部显示更高的 ID)。为了做到这一点,我尝试在列表的开头插入新模型:
cardModels.insert(0, new CardModel(nextID++));
不幸的是,我没有看到正确的小部件,而是一遍又一遍地看到 ID 为 0 的小部件:
我知道模型列表正在正确更新,因为我可以将其打印出来并按降序查看 ID。我假设有一些关于 flutter 如何检测到导致这种行为的小部件的变化,但在大量阅读之后,我仍然无法弄清楚。任何帮助将非常感激。此外,我在最终构建页面(包含 ListView 的小部件)的小部件中调用设置状态作为其子项之一:
btn = new FloatingActionButton(
onPressed: () => setState(_pageController.addCard),
tooltip: 'Upload File',
child: new Icon(Icons.file_upload),
);
_pageController 是修改模型列表的对象。如果这还不够,请告诉我,我很乐意提供更多代码或回答任何问题。
在 FloatingActionButton
上更改函数以插入新项目然后调用 setState
如:
cardModels.insert(0, new CardModel(nextId++)) ;
setState(() {
cardModels = cardModels;
});
希望对您有所帮助!
事实证明,我制作的 Card 小部件不需要是有状态的。我将其更改为无状态并解决了问题。不知道为什么让它们有状态会破坏它。
有一个简单的快速修复方法,使用 didWidgetUpdate
覆盖,
通过检查 oldWidget
中的 cardModels 对象是否与作为参数传递的 cardModels 相同。
像这样
@override
void didUpdateWidget(covariant Page oldWidget) {
if (widget.cardModels != oldWidget.cardModels) {
setState((){
cardModels = widget.cardModels;
});
}
super.didUpdateWidget(oldWidget);
}
完整示例如下
class Page extends material.StatefulWidget {
final List<CardModel> cardModels;
Page(this.cardModels);
@override
_PageState createState() => new _PageState(cardModels);
}
class _PageState extends material.State<Page> {
List<CardModel> cardModels;
@override
void initState(){
cardModels = widget.cardModels;
super.initState();
}
@override
void didUpdateWidget(covariant Page oldWidget) {
if (widget.cardModels != oldWidget.cardModels) {
setState((){
cardModels = widget.cardModels;
});
}
super.didUpdateWidget(oldWidget);
}
_PageState(this.cardModels);
@override
material.Widget build(material.BuildContext context) {
return new material.ListView(
children: cardModels.map((cardModel) => new Card(cardModel.cardID)).toList(),
);
}
}