Flutter布局开发时TabBarView占用额外多余空间是什么原因?
问题原因
Flutter 原生TabBarView内部默认使用最大高度约束,会强制占满父节点分配的所有可用空间,本身没有根据子组件高度自适应的逻辑,这就是你包裹Flexible/Expanded都不生效的核心原因。
解决方案
方案1:轻量替换方案(无滑动切换需求优先选)
如果不需要左右滑动切换Tab的交互,可以直接去掉TabBarView,通过监听TabController的索引变化切换显示内容,就能完全保留自适应高度的特性,修改后的VideoList代码如下:
class VideoListState extends State<VideoList> with SingleTickerProviderStateMixin { late TabController _controller; @override void initState() { super.initState(); _controller = TabController(length: 1, vsync: this); // 监听Tab切换刷新布局 _controller.addListener(() { setState(() {}); }); } @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Container( color: Colors.redAccent, height: 35, child: TabBar( controller: _controller, tabs: [ Tab( child: Text("Video 1"), ) ], ), ), // 直接根据索引切换子组件,自动适配子组件高度 Container( color: Colors.yellow, child: [VideoPlayer()][_controller.index], ) ], ); } }
如果需要切换动画,可以把上面的索引切换部分替换成AnimatedSwitcher组件即可。
方案2:保留TabBarView滑动能力的方案
如果需要保留左右滑动切换Tab的交互,需要通过GlobalKey提前计算每个Tab子组件的高度,动态设置TabBarView的高度:
- 给每个Tab的子组件绑定
GlobalKey,在组件渲染完成后获取其高度存储 - 监听
TabController的索引变化,切换时更新TabBarView的高度值 - 用
SizedBox包裹TabBarView,将高度设置为当前选中Tab的高度
根布局调整提示
你当前的根布局已经设置了mainAxisSize: MainAxisSize.min,上层的Flexible.loose配置无需改动,修改完VideoList部分即可实现Video区域高度自适应最小、剩余空间全部分给下半部分ListView的效果。
内容的提问来源于stack exchange,提问作者Rodrigo Silva
相关产品推荐
相关产品推荐

