【问题标题】:How do I insert widgets at the top of a ListView?如何在 ListView 顶部插入小部件?
【发布时间】:2018-08-10 03:48:12
【问题描述】:

简要说明:

在我所有的代码示例中,您会看到类似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(),
    );
  }
}

我期望的行为是,每当调用 build 方法(并且正确使用了 setState)时,ListView 应该被正确重建并包含按列表顺序排列的子小部件。如果我只是按顺序将新模型添加到 cardModels 中,它会成功地做到这一点:

cardModels.add(new CardModel(nextID++));

您可以看到小部件按顺序添加,并且它们的 id 正确递增:

但是,我希望在顶部插入较新的小部件(在顶部以更高的 id 显示)。为了做到这一点,我尝试在列表的开头插入新模型:

cardModels.insert(0, new CardModel(nextID++));

不幸的是,我没有看到正确的小部件,而是一遍又一遍地得到 id 为 0 的小部件:

我知道模型列表正在正确更新,因为我可以将其打印出来并按降序查看 id。我假设颤振如何检测导致这种行为的小部件更改,但经过大量阅读,我仍然无法弄清楚。任何帮助将非常感激。此外,我在最终构建页面(包含 ListView 的小部件)的小部件中调用 set state 作为其子项之一:

btn = new FloatingActionButton(
          onPressed: () => setState(_pageController.addCard),
          tooltip: 'Upload File',
          child: new Icon(Icons.file_upload),
        );

_pageController 是修改模型列表的对象。如果这还不够信息,请告诉我,我很乐意提供更多代码或回答任何问题。

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    有一个简单的快速修复,使用 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(),
        );
      }
    }
    

    【讨论】:

    • Awsome 为我节省了数小时的调试时间。
    【解决方案2】:

    事实证明,我制作的 Card 小部件不需要是有状态的。我将其更改为无状态,它解决了问题。不知道为什么让它们有状态会破坏它。

    【讨论】:

      【解决方案3】:

      FloatingActionButton 上更改函数以插入新项目,然后调用setState,如:

       cardModels.insert(0, new CardModel(nextId++)) ;
       setState(() {
           cardModels = cardModels;
       });
      

      希望对您有所帮助!

      【讨论】:

      • 我确实试过了,但并没有解决问题。刚刚意识到我制作的 Card 类不需要是有状态的。我将其切换为无状态并解决了问题。不过感谢您的帮助!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-08
      • 1970-01-01
      • 2021-03-15
      • 2018-09-17
      • 2018-04-18
      • 2019-06-25
      相关资源
      最近更新 更多