Flutter布局:如何使Widget高度为同Row内另一Widget的指定比例?
解决思路及代码实现
要让红色Widget的高度以黄色Widget的实际渲染高度为基准(最大为其一半),同时自身文本过长时能自动缩小,你可以用以下两种方式实现:
方法一:GlobalKey动态获取黄色Widget高度(简单直接)
通过GlobalKey获取黄色Widget的渲染高度,动态限制红色Widget的最大高度:
class _MyPageState extends State<MyPage> { final yellowKey = GlobalKey(); double? yellowHeight; @override void didChangeDependencies() { super.didChangeDependencies(); // 延迟获取高度,确保Widget完成渲染 WidgetsBinding.instance.addPostFrameCallback((_) { if (yellowKey.currentContext != null) { final renderBox = yellowKey.currentContext!.findRenderObject() as RenderBox; setState(() { yellowHeight = renderBox.size.height; }); } }); } @override Widget build(BuildContext context) { return Container( color: Colors.blue, width: double.infinity, height: MediaQuery.of(context).size.height * 0.5, // 外层高度由屏幕决定 child: Row( children: [ // 红色Widget:最大高度为黄色的一半,文本过长自动缩小 Container( color: Colors.red, constraints: yellowHeight != null ? BoxConstraints(maxHeight: yellowHeight! / 2) : const BoxConstraints(), child: FittedBox( child: const Text("红色文本,过长会自动缩小"), ), ), const SizedBox(width: 10), // 黄色Widget:用GlobalKey标记以获取高度 Container( key: yellowKey, color: Colors.yellow, child: FittedBox( child: const Text("黄色文本,长度变化会改变自身高度"), ), ), ], ), ); } }
方法二:CustomMultiChildLayout(精准布局控制)
通过自定义多子布局,在布局阶段直接让红色Widget的高度依赖黄色Widget的高度:
class _MyPageState extends State<MyPage> { static const yellowId = 1; static const redId = 2; @override Widget build(BuildContext context) { return Container( color: Colors.blue, width: double.infinity, height: MediaQuery.of(context).size.height * 0.5, child: CustomMultiChildLayout( delegate: _HeightDependentLayoutDelegate(), children: [ LayoutId( id: yellowId, child: Container( color: Colors.yellow, child: FittedBox( child: const Text("黄色文本,长度变化会改变自身高度"), ), ), ), LayoutId( id: redId, child: Container( color: Colors.red, child: FittedBox( child: const Text("红色文本,过长会自动缩小"), ), ), ), ], ), ); } } class _HeightDependentLayoutDelegate extends MultiChildLayoutDelegate { @override void performLayout(Size size) { // 先布局黄色Widget,获取其实际高度 final yellowSize = layoutChild(_MyPageState.yellowId, BoxConstraints.loose(size)); positionChild(_MyPageState.yellowId, Offset(size.width - yellowSize.width, 0)); // 给红色Widget设置最大高度为黄色的一半,再进行布局 final redMaxHeight = yellowSize.height / 2; final redSize = layoutChild( _MyPageState.redId, BoxConstraints.loose(Size(size.width - yellowSize.width - 10, redMaxHeight)), ); positionChild(_MyPageState.redId, Offset(0, (yellowSize.height - redSize.height) / 2)); } @override bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) { return true; } }
说明
- 两种方案都能满足需求:红色Widget最大高度为黄色Widget的一半,当红色文本过长时,
FittedBox会自动缩小文本适配高度,绝不会超过限制。 - 方法一适合简单场景,代码量少;方法二更适合复杂布局场景,能精准控制子Widget的位置和尺寸。
内容的提问来源于stack exchange,提问作者MrKew
相关产品推荐
相关产品推荐

