如何在ListView中优雅的嵌套ListView

cubegao 2021-07-06 PM 723℃ 0条

前言

日常的开发工作中,经常会遇到列表中嵌套ListView的需求。具体情况也分为两种。

1.竖向ListView嵌套横向ListView

常见的需求:竖向ListView行数不限制,横向ListView的列数不限制。具体情况如下图。

代码如下:

 ListView(
          children: [
            Text('ListView'),
            Stack(
              children: [
                IgnorePointer(
                  child: Opacity(
                    opacity: 0.0,
                    child: Item(),
                  ),
                ),
                SizedBox(width: double.infinity),
                Positioned.fill(
                  child: ListView.builder(
                    scrollDirection: Axis.horizontal,
                    itemBuilder: (_, index) => Item(),
                  ),
                ),
              ],
            ),
          ],
        )

Stack存在无Positioned包裹的子组件,决定Stack尺寸的是无位置的组件中的最大的尺寸,Positioned不会影响Stack的尺寸。(当然如果子类全部是Positioned包裹的子组件,Stack会将自身尺寸设置为父级布局约束所允许的最大尺寸,为对齐子组件创造条件。)。
此处用Positioned.fill,让ListView尽量占满整个Stack
接下来设置宽度,利用SizedBox的向下传递约束,向上传递尺寸的特性。用SizedBox(width: double.infinity)把宽度撑开到整个屏幕的宽度。
接下来算出Item的高度,用Item的高度撑开Stack的高度。
此处用Item的初衷只是为了定制高度,不能让Item显示在屏幕上,所以用Opacity隐藏Item,为了忽略掉事件响应,最后用上IgnorePointer

2.竖向ListView嵌套竖向ListView

这类需求是由于父列表和子列表的行数都不确定。处理也比较简单。

ListView(
          children: [
            Text('ListView'),
            ListView.builder(
                    shrinkWrap: true,                           
            physics: NeverScrollableScrollPhysics(),
                    itemBuilder: (_, index) => Item(),
                  ),
          ],
        )

通过设置shrinkWrap来固定ListView的高度,禁用滑动事件,让外面的ListView响应滑动事件就行了。
需要注意的是使用shrinkWrap,会一次性加载出所有的Item。如果数量太多,会出现内存问题。这时候可以通过父ListView和子ListView共用一个ScrollController来解决。代码如下:

ScrollController _scrollController;
  ListView(
    controller: _scrollController,
      children: [
          ListView(
                controller:_scrollController,
          ),
    ],
   )
标签: Flutter, ListView

非特殊说明,本博所有文章均为博主原创。

评论啦~