Flutter中如何让两个Expanded组件根据子组件适配屏幕空间
实现动态布局:短文本时容器填充剩余空间,长文本时平分屏幕
问题分析
当前布局的核心矛盾:
- 用两个
Expanded时,短文本会被强制拉伸至屏幕一半高度,导致文本与容器间出现空白间隙 - 将文本的
Expanded替换为Flexible后,文本仅占自身高度,但容器无法完全填充剩余空间,底部会出现空白
需要实现的效果:
- 短文本时:文本占自身所需高度,容器填充文本下方的全部剩余空间
- 长文本时:文本与容器各占屏幕一半高度
解决方案
通过LayoutBuilder获取可用布局高度,结合ConstrainedBox限制文本区域的最大高度,再用Expanded让容器自动填充剩余空间。代码示例如下:
import 'package:flutter/material.dart'; class HomePage extends StatelessWidget { const HomePage({super.key}); final String longText = ''' Vestibulum dapibus sit amet ante et vehicula. Aliquam erat volutpat. Pellentesque ut velit odio. Nam varius interdum urna ac gravida. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur dapibus in enim nec porta. Praesent tortor diam, tempus a massa eget, mattis imperdiet tellus. Aliquam porta pellentesque tellus sit amet dapibus. Vivamus dolor dui, dapibus sed risus ac, pellentesque convallis mauris. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus egestas metus eget ipsum pretium scelerisque. Nulla tempus ligula venenatis faucibus suscipit. Aenean est tortor, elementum fermentum ullamcorper a, consectetur nec erat. Quisque tincidunt finibus metus, eget vulputate turpis volutpat ac. Vivamus consectetur at ligula ac semper. Duis a justo sed tortor egestas sodales sed vitae sem. Mauris efficitur finibus lectus quis lacinia. Mauris velit odio, finibus et ipsum et, maximus iaculis diam. Phasellus ligula mi, gravida in enim et, fermentum tempus quam. Integer fermentum orci risus, eget aliquam nulla posuere eu. Donec dictum tristique nunc, in ullamcorper mi pulvinar ac. Integer sit amet laoreet nisi. Donec aliquet nibh nec rutrum aliquet. Mauris rutrum non ipsum et volutpat. '''; final String shortText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris venenatis hendrerit lectus sit amet venenatis.'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Home Page'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: LayoutBuilder( builder: (context, constraints) { // 获取当前布局的可用最大高度,扣除padding后的实际可分配空间 final halfAvailableHeight = constraints.maxHeight / 2; return Column( children: [ // 限制文本区域的最大高度为可用高度的一半 ConstrainedBox( constraints: BoxConstraints(maxHeight: halfAvailableHeight), // 加入SingleChildScrollView避免长文本溢出,可根据需求移除(移除后文本会截断) child: SingleChildScrollView( child: Text( shortText, // 切换为longText测试长文本效果 ), ), ), // Expanded自动填充剩余空间 Expanded( child: Container( color: Colors.teal, ), ), ], ); }, ), ), ); } }
原理说明
- LayoutBuilder:获取父容器的可用高度,确保能准确计算出屏幕一半的高度值
- ConstrainedBox:限制文本区域的最大高度为可用高度的一半,保证长文本时不会占用超过一半的屏幕空间
- SingleChildScrollView:可选组件,避免长文本超出最大高度时出现溢出警告,让内容可滚动(若不需要滚动,可直接移除,文本会自动截断)
- Expanded:让容器自动填充文本下方的剩余空间,短文本时占满剩余区域,长文本时刚好占另一半屏幕
内容的提问来源于stack exchange,提问作者sm-sayedi
相关产品推荐
相关产品推荐

