Flutter中如何让Expanded组件高度自适应内部ListView的内容大小
Flutter布局问题解决方案
问题根因
- 外层嵌套
SingleChildScrollView时,内部Column的高度约束为无限值,而Expanded组件的作用是基于父容器的有限高度分配剩余空间,在无限高度约束下Expanded会收缩到最小尺寸,导致内部ListView被压缩。 - 代码中为
SingleChildScrollView的子组件强制设置了height: MediaQuery.of(context).size.height,限制了整个页面内容高度只能等于屏幕高度,当页面内容超出屏幕高度时底部会被截断,同时也会挤压内部ListView的可用高度。
修复步骤
- 移除
SingleChildScrollView内部SizedBox的height属性,无需固定页面高度,让滚动容器自适应内容总高度。 - 删除两个包裹
ListView.builder的Expanded组件,无需占用父容器剩余空间,让ListView根据内容自行计算高度。 - 为两个
ListView.builder都配置shrinkWrap: true和physics: NeverScrollableScrollPhysics():shrinkWrap: true让ListView根据子元素总高度自适应自身尺寸,不会无限拉伸physics: NeverScrollableScrollPhysics()禁用内部ListView的滚动能力,滚动逻辑统一交给外层的SingleChildScrollView处理
关键修改代码示例
body: SingleChildScrollView( child: SizedBox( width: MediaQuery.of(context).size.width, // 删掉原来的height属性 child: Container( padding: EdgeInsets.all(5.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding(padding: EdgeInsets.all(5.0)), Text( 'Cores:', style: new TextStyle( fontWeight: FontWeight.bold, fontSize: 16.0, ), ), // 删掉原来的Expanded Obx( () => ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, // 新增 physics: NeverScrollableScrollPhysics(), // 新增 itemCount: controller.produtosCoresList.length, itemBuilder: (BuildContext context, int index) { return ListTile( dense: true, contentPadding: EdgeInsets.only(left: 3.0, right: 0.0), visualDensity: VisualDensity(horizontal: 0, vertical: -4), title: Text(controller.produtosCoresList[index].cor), leading: Radio( value: controller.produtosCoresList[index].cor, groupValue: 'ROSA', onChanged: (value) {}, activeColor: Colors.red.shade800, ), ); }), ), Padding(padding: EdgeInsets.all(5.0)), Divider(height: 5.0, color: Colors.black), Padding(padding: EdgeInsets.all(5.0)), Text( 'Tamanho:', style: new TextStyle( fontWeight: FontWeight.bold, fontSize: 16.0, ), ), // 删掉原来的Expanded Obx( () => ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, physics: NeverScrollableScrollPhysics(), // 新增 itemCount: controller.produtosTamanhoList.length, itemBuilder: (BuildContext context, int index) { return ListTile( dense: true, contentPadding: EdgeInsets.only(left: 3.0, right: 0.0), visualDensity: VisualDensity(horizontal: 0, vertical: -4), title: Text(controller.produtosTamanhoList[index].tam), leading: Radio( value: controller.produtosTamanhoList[index].tam, groupValue: 'IG', onChanged: (value) {}, activeColor: Colors.red.shade800, ), ); }, ), ), // 剩余其他组件保持原有逻辑即可 ], ), ), ), )
内容的提问来源于stack exchange,提问作者Debora Mezzalira
相关产品推荐
相关产品推荐

