Flutter Column嵌套Row时Expanded内Stack垂直对齐失效
问题现象
开发自定义Stepper表头时,分割线对齐规则要求:
- 首项分割线居中右对齐
- 中间项分割线居中对齐
- 末项分割线居中左对齐
当前布局异常:Stack被Expanded包裹作为Row的子组件,当Row外层嵌套Column时,Stack的垂直对齐规则失效,内容固定停留在顶部;去掉外层Column直接把Row放在SafeArea下时对齐正常,控制台无报错。
异常效果:
预期效果:
问题根因
这是Flutter布局约束传递的默认规则导致的:
Row直接在SafeArea下时,会拿到父组件传递的固定高度约束,内部Expanded包裹的Stack会占满分配的高度,Alignment.center的垂直居中规则正常生效。Row嵌套在Column中时,Column对非弹性子组件传递无界高度约束,Row默认会收缩到内部子组件的高度;此时Stack没有明确高度约束,会自动适配子组件高度,Align的垂直居中因为父容器无剩余垂直空间,直接将内容摆放在顶部。
修复方案
方案1:给Row指定固定高度(最简单,适配固定高度的Stepper场景)
Stepper表头指示器本身高度固定,直接给Row外层套固定高度的SizedBox即可,同时把Row的垂直对齐改成居中:
class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return SafeArea( child: Column( children: [ // 新增固定高度容器 SizedBox( height: 32, // 可根据UI需求调整,大于序号直径22即可 child: Row( // 垂直对齐改为居中 crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Stack( children: [ Align( alignment: Alignment.centerRight, child: LayoutBuilder( builder: (ctx, constraints) => Container( width: constraints.maxWidth / 2.0, height: 1, color: Colors.black, ), ), ), Align( alignment: Alignment.center, child: Container( height: 22, width: 22, decoration: BoxDecoration( borderRadius: BorderRadius.circular(11.0), color: Colors.blue, // 替换为你的Palette.primary即可 ), child: Center( child: Text( '1'.substring(0, 1), maxLines: 1, style: TextStyle( fontSize: 14, overflow: TextOverflow.clip, color: Colors.white), ), ))), ], ), ), Expanded( child: Stack( children: [ Align( alignment: Alignment.center, child: LayoutBuilder( builder: (ctx, constraints) => Container( width: constraints.maxWidth, height: 1, color: Colors.black, ), ), ), Align( alignment: Alignment.center, child: Container( height: 22, width: 22, decoration: BoxDecoration( borderRadius: BorderRadius.circular(11.0), color: Colors.blue, ), child: Center( child: Text( '2'.substring(0, 1), maxLines: 1, style: TextStyle( fontSize: 14, overflow: TextOverflow.clip, color: Colors.white), ), ))) ], ), ), Expanded( child: Stack( children: [ Align( alignment: Alignment.centerLeft, child: LayoutBuilder( builder: (ctx, constraints) => Container( width: constraints.maxWidth / 2.0, height: 1, color: Colors.black, ), ), ), Align( alignment: Alignment.center, child: Container( height: 22, width: 22, decoration: BoxDecoration( borderRadius: BorderRadius.circular(11.0), color: Colors.blue, ), child: Center( child: Text( '3'.substring(0, 1), maxLines: 1, style: TextStyle( fontSize: 14, overflow: TextOverflow.clip, color: Colors.white), ), ))) ], ), ) ], ), ), ], ), ); } }
方案2:拉伸Row适配可用高度(不需要写死高度的场景)
如果不想固定高度,将Row的crossAxisAlignment改为CrossAxisAlignment.stretch让Row占满垂直可用空间,同时给每个Stack加上alignment: Alignment.center即可:
Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded( child: Stack( alignment: Alignment.center, // 新增Stack对齐属性 children: [/* 原有子组件不变 */] ), ), // 其余两个Expanded内的Stack同样添加alignment: Alignment.center即可 ] )
两种方案修改后,无论外层嵌套多少层Column,分割线和序号都会保持垂直居中,和预期效果一致。
内容的提问来源于stack exchange,提问作者Ariel
相关产品推荐
相关产品推荐

