场景:
实现一个弹性布局,卡片为动态高度,高度由左半边内容决定。右边内容自动占满高度,并使用spaceBetween对齐。
最终效果:
问题:
倘若Row组件无固定高度(height is unconstrained),其子组件不会自动占满高度,Column组件同理。
Card( child: Padding( padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 1, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '王嘉然', style: TextStyle(fontSize: 18), ), Padding(padding: EdgeInsets.only(top: 5)), Text( '年龄:18', style: TextStyle(color: Colors.grey, fontSize: 14), ), Text( '就读院校:枝江市枝江大学', style: TextStyle(color: Colors.grey, fontSize: 14), ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '代表作:', style: TextStyle(color: Colors.grey, fontSize: 14), ), Expanded( child: Text( 'https://www.bilibili.com/video/BV1FX4y1g7u8', style: TextStyle(color: Colors.grey, fontSize: 14), ), ), ], ), ], ), ), Expanded( flex: 0, child: Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'A-SOUL', style: TextStyle(fontSize: 14), ), Text( '关注嘉然,顿顿解馋!', style: TextStyle(fontSize: 12), ), ], )), ], ), ),);
加上高度(h=150)后正常。
Card( child: Container( // 这里固定高度 height: 150, padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 1, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '王嘉然', style: TextStyle(fontSize: 18), ), Padding(padding: EdgeInsets.only(top: 5)), Text( '年龄:18', style: TextStyle(color: Colors.grey, fontSize: 14), ), Text( '就读院校:枝江市枝江大学', style: TextStyle(color: Colors.grey, fontSize: 14), ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '代表作:', style: TextStyle(color: Colors.grey, fontSize: 14), ), Expanded( child: Text( 'https://www.bilibili.com/video/BV1FX4y1g7u8', style: TextStyle(color: Colors.grey, fontSize: 14), ), ), ], ), ], ), ), Expanded( flex: 0, child: Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'A-SOUL', style: TextStyle(fontSize: 14), ), Text( '关注嘉然,顿顿解馋!', style: TextStyle(fontSize: 12), ), ], )), ], ), ),);
但固定高度并不是我们想要的,因为内容长度不固定。
解决方案:
使用以下组件,将其子部件的大小调整为子部件的最大内在高度(宽度)。
IntrinsicHeighthttps://api.flutter.dev/flutter/widgets/IntrinsicHeight-class.htmlIntrinsicWidthhttps://api.flutter.dev/flutter/widgets/IntrinsicWidth-class.html
我们为Row组件添加IntrinsicHeight父组件后,观察布局,发现高度不再是unconstrained。
原因是这个类会在布局最后阶段(final layout phase)加入一个推测布局(speculative layout)以计算高度,所以组件能获取到高度值。
但因为这个能力其开销较大,在能固定高度的情况下,应尽量少的使用此类组件。
最终代码:
Card( child: Padding( padding: const EdgeInsets.all(10), child: IntrinsicHeight( // 使用IntrinsicHeight包裹Row组件使其自动推测得到高度 child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 1, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '王嘉然', style: TextStyle(fontSize: 18), ), Padding(padding: EdgeInsets.only(top: 5)), Text( '年龄:18', style: TextStyle(color: Colors.grey, fontSize: 14), ), Text( '就读院校:枝江市枝江大学', style: TextStyle(color: Colors.grey, fontSize: 14), ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '代表作:', style: TextStyle(color: Colors.grey, fontSize: 14), ), Expanded( child: Text( 'https://www.bilibili.com/video/BV1FX4y1g7u8', style: TextStyle(color: Colors.grey, fontSize: 14), ), ), ], ), ], ), ), Expanded( flex: 0, child: Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'A-SOUL', style: TextStyle(fontSize: 14), ), Text( '关注嘉然,顿顿解馋!', style: TextStyle(fontSize: 12), ), ], )), ], ), ), ),);