Flutter 动画列表:有条件地添加 ListView 项

Posted

技术标签:

【中文标题】Flutter 动画列表:有条件地添加 ListView 项【英文标题】:Flutter Animated List: Conditionally add ListView item 【发布时间】:2019-10-24 22:49:06 【问题描述】:

我的颤振项目中有一个动画列表。

对于该列表中的每个元素,我都有一个从 Firestore 流中动态放置的按钮网格。有时会在网格中返回 10 个项目,但有时会返回 0 个项目。

当按下列表元素中网格上的按钮时,它将搜索 Firestore 并在下面的下一个列表元素中创建一个新的按钮网格。

我遇到的问题是,当它返回 0 个网格按钮时,我不希望它创建一个新的列表元素(一个没有网格按钮的空列表元素)。我尝试返回一个大小为 0 的容器作为解决方法,但动画列表仍然给它一些高度,所以你可以看到有问题。我也明白这是不好的做法,因为列表中有不可见的空列表元素。

我以字符串形式的食物列表开始:

  List foodListGrids = ['breads','drinks']

然后我有一个动画列表:

AnimatedList(
  shrinkWrap: true,
  physics: NeverScrollableScrollPhysics(),
  key: _FoodandDrinkKey,
  initialItemCount: foodListGrids.length,
  itemBuilder: (context, index, animation) 
        return SizeTransition(
                   sizeFactor: animation,
                   child: buildButtonGridItemsMenu(index),
             );
        ,
   ),

我将 AnimatedList 的大小设置为食物列表的长度。

我将 Animated List 的子级设置为搜索 firebase 并返回带有按钮网格的卡片的类,如下所示:

StreamBuilder(
        stream: Firestore.instance
            .collection(widget.categoryType)
            .where(widget.relationship, isEqualTo: widget.searchString)
            .snapshots(),
        builder: (BuildContext context, AsyncSnapshot snapshot) 
          if (!snapshot.hasData) 
            return Container(width: 0, height: 0,);
           else if (snapshot.hasData) 
            List<Widget> widgetList = [];
            List<DocumentSnapshot> documentList = snapshot.data.documents;
            if (documentList.length > 0) 
              for (int i = 0; i < documentList.length; i++) 
                widgetList.add(ButtonTheme(
                  minWidth: 16,
                  height: 30,
                  child: GridButton(snapshot, i, widget.listIndex),
                ));
              
              return Container(
                  width: double.infinity,
                  child: Wrap(
                    children: widgetList,
                    alignment: WrapAlignment.center,
                  ));
             else
              return Text('NO DATA BECAUSE NUMBER OF GRID ITEMS IS 0');
            
           else 
            return Text('NO DATA BECAUSE GRID ITEMS CALL IS NULL');
          
        ,
      ),

然后在每个网格按钮的按下方法中,我添加一个新的列表元素,如下所示:

void _insertCategoryGridItem(String id, int index) 
  if (!foodListGrids.contains(id)) 
    foodListGrids.add(id);
    _FoodandDrinkKey.currentState.insertItem(index + 1);
  

问题是先有鸡还是先有蛋,我将尝试在下面展示:

    列表项是从食物列表中的索引 0 生成的,所有流数据都是来自食物列表索引 0 的 firebase 结果。 在按下第一个列表行中的网格项时,按下以添加具有一组新网格项的新列表行。然后,这将更新食物列表数组并调用列表以添加新的网格按钮行。问题是因为这是在第一行网格的 onpressed 中,不知道下一行将返回什么,因此无法知道它是否会在下一个列表行中返回大小为 0 的网格当前的设置方式。

我尝试返回空值,0 宽度和高度的容器,但没有运气。我不确定我能做些什么来解决它。

感谢您的帮助

【问题讨论】:

这能回答你的问题吗? How to update data in an AnimatedList in Flutter 【参考方案1】:

我不确定我是否正确,但似乎我在使用 AnimatedList 和来自 Firestore 的数据流时遇到了同样的问题。问题出在AnimatedListinitialItemCount: 属性中。

就我而言,我想通过两种方式更改 AnimtedList

    我想手动添加一个项目并用动画显示它。 我希望如果列表因流中的新数据部分而发生更改 - 我希望更新列表时没有插入动画和错误(超出范围)。

为了解决这个问题,我做了一个肮脏的 hack:当流中有更新时,我重新初始化列表的键,在你的情况下它是 _FoodandDrinkKey。因此,在您构建 AnmatedList 之前,只需重新初始化您的密钥 _listKeyUserNotes = GlobalKey();,这就是 List 如何“忘记”它的 initialItemCount 并将呈现新数据而不会出现任何超出范围的错误。 当您想手动添加带有动画的新项目时 - 使用 insert()

key: _FoodandDrinkKey,
initialItemCount: foodListGrids.length,

希望这是有道理的。

【讨论】:

以上是关于Flutter 动画列表:有条件地添加 ListView 项的主要内容,如果未能解决你的问题,请参考以下文章

如何有条件地将小部件添加到列表中?

Flutter ListVİew 总是在向上或向下滚动时重新渲染

Flutter - 动画列表中容器的消失

带有小部件列表的 Flutter 动画切换器

如何在 Angular 2 中有条件地添加动画

Flutter null 安全条件小部件