Flutter_ConstraintLayout
Flutter_ConstraintLayout copied to clipboard
ConstraintLayout 能放在listview里面用吗
可以
`class VisualizeReportedRecordWidget extends StatelessWidget { final VisualizeReportedRecordReq visualizeReportedRecordReq;
const VisualizeReportedRecordWidget( {required this.visualizeReportedRecordReq, Key? key}) : super(key: key);
@override Widget build(BuildContext context) { var idImage1 = ConstraintId("idImage1"); var idRow1 = ConstraintId("idRow1"); var idStoreName = ConstraintId("idStoreName"); var idComment = ConstraintId("idComment"); var idPhoto = ConstraintId("idPhoto"); var idSb1 = ConstraintId("idSb1");
var time = getFormatDateC3().safetyFormat(
getFormatDateFinal().safetyParse(visualizeReportedRecordReq.ctime));
var checkTime = "";
var state = "";
var checker = '';
var isShowState = true;
var isShowCommon = true;
var comment = "";
switch (visualizeReportedRecordReq.status) {
case 2:
checker = visualizeReportedRecordReq.operatorName ?? "";
checkTime = getFormatDateC1().safetyFormat(
getFormatDateFinal().safetyParse(visualizeReportedRecordReq.utime));
state = AdS.of(context).adHint196();
comment = visualizeReportedRecordReq.operatorRemark ?? "";
break;
case 5:
checker = visualizeReportedRecordReq.operatorName ?? "";
checkTime = getFormatDateC1().safetyFormat(
getFormatDateFinal().safetyParse(visualizeReportedRecordReq.utime));
state = AdS.of(context).adHint197();
comment = visualizeReportedRecordReq.operatorRemark ?? "";
break;
default:
isShowState = false;
isShowCommon = false;
break;
}
var storeName = visualizeReportedRecordReq.store ?? "";
List<AssetsInfo> assetsInfoList = [];
visualizeReportedRecordReq.img?.split("|").map((e) {
AssetsInfo assets = AssetsInfo();
assets.serverUrl = e;
assetsInfoList.add(assets);
}).toList();
return ConstraintLayout(
height: wrapContent,
children: [
Image.asset(
ImagePath.wrapAssetsPng("ad_ic_flow_chapter"),
width: 20,
height: 20,
package: AdConfigs.package,
).apply(
constraint: Constraint(
id: idImage1,
top: parent.top,
left: parent.left,
margin: const EdgeInsets.only(left: 16, top: 4))),
Row(
children: [
Text(
time,
style: const TextStyle(
color: ColorsHelper.color333333,
fontSize: 18,
fontWeight: FontWeight.bold),
),
const SizedBox(
width: 8,
),
if (isShowState)
Container(
padding: const EdgeInsets.symmetric(horizontal: 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(1),
border: Border.all(
color: ColorsHelper.colorFF4545, width: 0.5)),
child: Text(
state,
style: const TextStyle(
color: ColorsHelper.colorFF4545, fontSize: 12),
),
)
],
).apply(
constraint: Constraint(
id: idRow1,
left: idImage1.right,
top: idImage1.top,
margin: const EdgeInsets.only(left: 12),
bottom: idImage1.bottom)),
Text(
storeName,
style: const TextStyle(color: ColorsHelper.color666666, fontSize: 12),
).apply(
constraint: Constraint(
id: idStoreName,
left: idRow1.left,
top: idRow1.bottom,
margin: const EdgeInsets.only(top: 4))),
Container(
decoration: BoxDecoration(
color: ColorsHelper.colorF4F4F4,
borderRadius: BorderRadius.circular(2)),
padding: const EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
ccImage(ImagePath.wrapAssetsPng('ad_ic_head_photo'),
package: AdConfigs.package,
width: 32,
borderRadius: BorderRadius.circular(2)),
const SizedBox(
width: 4,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
AdS.of(context).adHint195(),
style: const TextStyle(
color: ColorsHelper.color333333, fontSize: 14),
),
Expanded(
child: Text(
checkTime,
textAlign: TextAlign.end,
style: const TextStyle(
color: ColorsHelper.color999999, fontSize: 12),
))
],
),
Text(
checker,
style: const TextStyle(
color: ColorsHelper.color999999, fontSize: 12),
)
],
)),
],
),
const SizedBox(
height: 10,
),
const CCDivider(
color: ColorsHelper.colorE0E0E0,
),
const SizedBox(
height: 10,
),
Text(
comment,
style: const TextStyle(
color: ColorsHelper.color666666, fontSize: 14),
),
],
),
).apply(
constraint: Constraint(
id: idComment,
left: idRow1.left,
top: idStoreName.bottom,
right: parent.right,
width: matchConstraint,
visibility:
isShowCommon ? CLVisibility.visible : CLVisibility.gone,
margin: const EdgeInsets.only(right: 16, top: 12))),
ShowMediaWidget(
isEnable: false,
assetsInfoList: assetsInfoList,
maxSize: 96,
padding: EdgeInsets.zero,
).apply(
constraint: Constraint(
id: idPhoto,
top: idComment.bottom,
left: idRow1.left,
width: matchConstraint,
right: parent.right,
margin: const EdgeInsets.only(right: 16),
goneMargin: const EdgeInsets.only(top: 12),
)),
const SizedBox(
height: 24,
).apply(
constraint:
Constraint(id: idSb1, left: idRow1.left, top: idPhoto.bottom)),
const CCVerticalDivider(
width: 1,
color: ColorsHelper.colorE0E0E0,
).apply(
constraint: Constraint(
id: ConstraintId("sb2"),
left: idImage1.left,
right: idImage1.right,
top: idImage1.bottom,
bottom: idSb1.bottom,
height: matchConstraint,
margin: const EdgeInsets.only(top: 4)),
),
],
);
} }`
您好,当我在listview里面使用该布局时,高的wrapContent不起作用,怎么调试都是44.5。请问是有什么限制导致的吗。期待你的答复。
你用错了,当你把 ConstraintLayout 的高度设置为 wrapContent 时,ConstraintLayout 的自身大小是由那些宽高为 wrapContent 或 fixed size 的子元素的大小(以及它们的 margin)撑起来的。那些宽高为 matchParent 或 matchConstraint 的子元素不会影响 ConstraintLayout 的自身大小。
如果一部分子元素相对于顶部对齐,一部分相对于底部对齐,是不会把 ConstraintLayout 撑到你的预期大小的。
你的布局方式应该改为始终相对于一个方向去对齐。
好的,谢谢您的解惑。
钉在这里,供后面的小伙伴参考。
ConstraintLayout( height: wrapContent, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( height: 20, ), Text("test"), Container( child: Text("test2"), ), Container( color: Colors.redAccent, child: Text("test3"), ) ], ).applyConstraint( id: idColumn, top: parent.top, left: parent.left, height: wrapContent, width: matchConstraint, right: parent.right), ], )
您好,我还想再请教一下。我的布局想这样的,放在listview里面, 高度设置为wrapContent,这时高度是计算不出来的吗?,导致界面啥也不显示。
稍等我研究下
).applyConstraint(
// id: idColumn,
top: parent.top,
// left: parent.left,
height: wrapContent,
width: matchParent,
// width: matchConstraint,
// right: parent.right,
),
],
改成这样就好了。宽度从 matchConstraint 改为 matchParent,删除横向的约束
这里牵扯到布局优先级的问题,整个 ConstraintLayout 中只有一个子元素,这里要指望 Column 把 ConstraintLayout 撑起来,那么 Column 的宽度就不能再是 matchConstraint,因为这样会让 parent 先布局,Column 后布局。这导致 parent 没有被任何元素撑起来,实际宽高为 0。就导致什么也展示不出来了 。我后面会写一篇原理分析的文章好好讲讲这些 “有坑” 的注意点。
约束布局的核心原理是按照优先级来布局,A 约束在 B 的右边,则 A 的布局优先级比 B 低。也就是要等 B 布局之后再布局 A。
你这里在横向上把宽高设为 matchConstraint,导致 Column 和 parent 产生了约束依赖关系,parent 的布局优先级高于 Column。因为要等 parent 的 left 和 right 确定以后,才能确定 Column 的宽度。
当你改用 matchParent 以后,横向上的约束依赖关系就被打破了,因为在布局 Column 时可以拿到 parent 的宽度,也就是 ListView 的宽度。这就使得 Column 可以先于 parent 布局,parent 就能被撑起来,界面展示就恢复正常了!
其实最主要的还是约束布局的约束推断算法不够聪明,不然你这么写也可以保证不出问题的
根据您的详细的回复,我解决了我项目中遇到的问题,谢谢您!