ListView Builder的动态高度

7

我无法为列表视图构建器的列表项设置动态大小,每次都显示空白屏幕,但当我指定一个固定大小时它可以正常工作。

我尝试使用列来设置mainAxisSize=minimum,或者使用容器,因为我们知道容器会包装子元素的高度,但都没有效果。

 listItem (GuideLines news) =>Column(
    mainAxisAlignment: MainAxisAlignment.start,
    mainAxisSize:  MainAxisSize.min,
    children: <Widget>[Container(
      decoration: BoxDecoration(image: new DecorationImage(image: AdvancedNetworkImage(
        "${news.featured_image}",
        useDiskCache: true,
        cacheRule: CacheRule(maxAge: const Duration(days: 7)),
      ),fit: BoxFit.cover)),
      margin: EdgeInsets.only(bottom: 10.0),
      child: ListTile(
        onTap: (){
          print(news.web_link);
          Navigator.push(context, MaterialPageRoute(builder: (context) => NewsDetailsPage(news)));
        },
        title: new Container(
            margin: EdgeInsets.only(left: 30.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(top: 20.0),
                  child: new Text("${DateFormat("E, d MMM y").format(CommonService.dateFormat(news.publish_date.toString()))}", style: TextStyle(fontFamily: 'SF-Display-Regular' ,fontSize: 13.0 ,color: Colors.white),),
                ),
                SizedBox(height: 13.0),
                new Flexible(
                  child: new Container( width:  MediaQuery.of(context).size.width  *0.45,
                      child: Padding(
                        padding: const EdgeInsets.only(bottom: 20.0),
                        child: new Text("${news.title}" ,maxLines: 3, overflow: TextOverflow.ellipsis, style: TextStyle(fontFamily: 'SF-Display-Semibold' ,fontSize: 22.0 ,color: Colors.white),),
                      )


                  ),
                )
              ],
            )),
        trailing: Padding(
          padding: const EdgeInsets.only(right: 20),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[Icon(Icons.arrow_forward_ios, color: Colors.white),SizedBox(width: 8,)],
          ),
        ),
      ),


    )],
  );

外部Column有什么作用?为什么尾随的图标被包裹在Row和Padding中?标题的Column为什么具有属性:mainAxisSize: MainAxisSize.max?在Flexible小部件内,您有一个Container,里面是一个Padding小部件,您不需要这个Padding小部件,因为Container具有Padding属性。总的来说,我认为代码包含了很多不必要的东西。我认为对于你正在做的事情,你不应该使用ListItem并将其自定义到极致,而是编写自己的小部件。 - Martin Niederl
我将更新ListTile内的代码,但是ListTile内的代码与我的问题无关。我只想将ListTile包装到ListTile大小。 - Ayaz Khalid
2个回答

10

只需添加shrinkWrapphysics这两个属性,即可使列表高度动态变化。

ListView.builder(
   shrinkWrap: true,
   physics: NeverScrollableScrollPhysics(), //Optional                               
   itemCount: size,
   itemBuilder: (context, position) {}
),

如果我们不指定尺寸,滚动控制器将无法工作。对于大量列表,这也会导致非常大的延迟。 - ÄR Âmmãř Żąîñh
@ÄRÂmmãřŻąîñh 的 ListView.builder 只会加载适合屏幕的项目,当我们滚动屏幕时,它会加载更多数据。 如果您的列表有数千个或更多,则可以使用分页来处理。 - Muhammad Tameem Rafay
1
不,你试图在没有列表视图大小(高度)的情况下将所有列表组件加载到整个剩余屏幕上。如果您这样做,默认滚动物理效果将不起作用,因为它没有指定的大小,这就是为什么您通过使用 NeverScrollableScrollPhysics() 从列表视图中删除滚动功能,因此父滚动视图将从此获取滚动功能。我们将失去许多listview功能,例如scroll controller,cacheExtent等非常有用的功能。如果您将带有大小和不带大小的1000s记录的listview进行比较,您会看到性能上的巨大差异。 - ÄR Âmmãř Żąîñh
是的,对于动态高度,您可以仅使用此参数 "shrinkWrap: true"。 - Muhammad Tameem Rafay

3
你的代码问题在于,在Column中使用了一个Flexible小部件。 Flexible小部件会扩展到Column或Row的剩余空间。但是,仅在您限制了Column或Row小部件的大小时才有效。否则,由于剩余空间未受限制,因此Column中元素的大小将扩展到无限大。
当使用Flexible或Expanded小部件时,您始终需要限制其父级大小,否则您会收到以下错误:
RenderFlex children have non-zero flex but incoming height constraints are unbounded. When a column is in a parent that does not provide a finite height constraint, for example if it is in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining space in the vertical direction.
解决方案及清理代码:
Widget listItem(GuideLines news) {
  return Container(
    decoration: BoxDecoration(
      image: DecorationImage(
          image: AdvancedNetworkImage(
            "${news.featured_image}",
            useDiskCache: true,
            cacheRule: CacheRule(maxAge: const Duration(days: 7)),
          ),
          fit: BoxFit.cover),
    ),
    margin: EdgeInsets.only(bottom: 10.0),
    child: ListTile(
      onTap: () {
        print(news.web_link);
        Navigator.push(context, MaterialPageRoute(builder: (context) => NewsDetailsPage(news)));
      },
      title: Container(
        margin: EdgeInsets.only(left: 30.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(top: 20.0, bottom: 13.0),
              child: Text(
                "${DateFormat("E, d MMM y").format(CommonService.dateFormat(news.publish_date.toString()))}",
                style: TextStyle(fontFamily: 'SF-Display-Regular', fontSize: 13.0, color: Colors.white),
              ),
            ),
            Container(
              width: MediaQuery.of(context).size.width * 0.45,
              padding: const EdgeInsets.only(bottom: 20.0),
              child: new Text(
                "${news.title}",
                maxLines: 3,
                overflow: TextOverflow.ellipsis,
                style: TextStyle(fontFamily: 'SF-Display-Semibold', fontSize: 22.0, color: Colors.white),
              ),
            )
          ],
        ),
      ),
      trailing: Padding(
        padding: const EdgeInsets.only(right: 28),
        child: Icon(Icons.arrow_forward_ios, color: Colors.white),
      ),
    ),
  );
}

在您的情况下,这个灵活的小部件是多余的。

你能解释一下修复方法吗?我不明白它现在是如何工作的,因为之前我使用了容器但它没有起作用。 - Ayaz Khalid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接