Flutter报错RenderShrinkWrappingViewport不支持返回固有尺寸求解决
问题解决:CustomScrollView嵌套GridView的滚动冲突与布局报错
问题场景
在CustomScrollView内部组合多个Sliver组件,其中SliverFillRemaining中嵌套了GridView。为了让外层CustomScrollView统一处理滚动,设置了GridView的physics: NeverScrollableScrollPhysics(),同时将SliverFillRemaining的hasScrollBody设为false,但触发了以下布局报错:
The following assertion was thrown during performLayout(): RenderShrinkWrappingViewport does not support returning intrinsic dimensions. Calculating the intrinsic dimensions would require instantiating every child of the viewport, which defeats the point of viewports being lazy. If you are merely trying to shrink-wrap the viewport in the main axis direction, you should be able to achieve that effect by just giving the viewport loose constraints, without needing to measure its intrinsic dimensions.
报错原因
设置shrinkWrap: true的GridView会尝试计算自身固有尺寸,但SliverFillRemaining在hasScrollBody: false的情况下,会给子组件传递严格的尺寸约束,两者布局逻辑冲突,导致RenderShrinkWrappingViewport无法处理固有尺寸计算。
解决方案
- 移除GridView的
shrinkWrap: true:避免GridView触发固有尺寸计算逻辑 - 用Expanded包裹GridView:让GridView自适应SliverFillRemaining提供的可用空间
- 保留原有滚动配置:继续使用SliverFillRemaining的
hasScrollBody: false和GridView的physics: NeverScrollableScrollPhysics(),确保外层CustomScrollView全权处理滚动
修改后的代码
SearchViewBody 代码
class SearchViewBody extends StatelessWidget { const SearchViewBody({super.key, this.searchText = ""}); final String searchText; @override Widget build(BuildContext context) { return CustomScrollView( slivers: [ SliverToBoxAdapter( child: SearchViewAppBar(), ), SliverToBoxAdapter( child: SearchViewWhiteBox(searchText: searchText), ), SliverFillRemaining( hasScrollBody: false, fillOverscroll: true, child: BlocBuilder<SearchCubit,SearchState>( builder: (context,state){ if(state is SearchLoading) { return Container(color: Colors.white,child: LoadingWidget()); } else if(state is SearchSuccess){ if(state.products.isEmpty){ return Container(color: Colors.white,child: Center(child: Text("未找到内容"))); }else return Container( color: Colors.white, child: Expanded( child: SearchItemsList(state: state), ), ); } else if(state is SearchFailure) return Center(child: Text(state.message)); else return Container(); } ) ) ], ); } }
SearchItemsList 代码
class SearchItemsList extends StatelessWidget { const SearchItemsList({super.key,this.state}); final SearchSuccess? state; @override Widget build(BuildContext context) { return GridView.builder( padding: EdgeInsets.symmetric(horizontal: 20), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.7, crossAxisSpacing: 10, mainAxisSpacing: 10 ), itemCount: state!.products.length, scrollDirection: Axis.vertical, physics: NeverScrollableScrollPhysics(), itemBuilder: (context, index) { return SearchProductItem(product: state!.products[index]); } ); } }
内容的提问来源于stack exchange,提问作者ibrahim Ghareeb
相关产品推荐
相关产品推荐

