問題及場景
ListView 是 Flutter 開發者第一個學習到的 Widget,因為它可以滑動。一切都會運行得很好,直到 ListView 中的 Item 本身也是一個 ListView。你可能會看到 Flutter 建議你將內部的 ListView 的ShrinkWrap 屬性設置為 True。雖然錯誤消除了,但是威脅還在。因為 ShrinkWrap 屬性會將 ListView 一次性全部填充,算出所有高度,如果內部 ListView 的數據量比較大,那將產生性能問題,會有很大的風險掉幀、jank 和 stutters。
假設你遇到下面這樣的場景
final outerListChildren = <ListView>[ListView(children: <Wdiget>[...]),...
];return ListView.Builder(itemCount: outerListChildren.length,itemBuilder: (context, index) {return outerListChildren[index]}
)
然后我們按照 Flutter 的提示,將內部的 ListView 加上 shrinkWrap 和 physics 屬性如下
final outerListChildren = <ListView>[ListView(shrinkWrap: true,physics: const NeverScrollableScrollPhysics(),children: <Wdiget>[...]),...
];return ListView.Builder(itemCount: outerListChildren.length,itemBuilder: (context, index) {return outerListChildren[index]}
)
解決方法:
1、首先,將最外層的 ListView 改為 CustomScrollView
return CustomScrollView(children: outerListChildren}
)
2、然后我們將外部的 ListView 列表改為 SliverList 列表
final outerListChildren = <SliverList>[];
return CustomScrollView(children: outerListChildren}
)
3、所有 SliverList 添加 delegate,并使用 SliverChildBuilderDelegate 作為 value,_myWidgets
是之前的 inner ListView 需要顯示的內容
final outerListChildren = <SliverList>[SliverList(delegate: SliverChildBuilderDelegate(childCount: _myWidgets.length,(context, index) => _myWidgets[index]))
];
return CustomScrollView(children: outerListChildren}
)
至此,大功告成