Flutter_ConstraintLayout icon indicating copy to clipboard operation
Flutter_ConstraintLayout copied to clipboard

ConstraintLayout 能放在listview里面用吗

Open qflbai opened this issue 2 years ago • 12 comments

qflbai avatar Aug 01 '22 11:08 qflbai

可以

hackware1993 avatar Aug 02 '22 01:08 hackware1993

`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。请问是有什么限制导致的吗。期待你的答复。 1659405198715

924ae302101c36f1635d8e0cab3d9b5

qflbai avatar Aug 02 '22 01:08 qflbai

你用错了,当你把 ConstraintLayout 的高度设置为 wrapContent 时,ConstraintLayout 的自身大小是由那些宽高为 wrapContent 或 fixed size 的子元素的大小(以及它们的 margin)撑起来的。那些宽高为 matchParent 或 matchConstraint 的子元素不会影响 ConstraintLayout 的自身大小。

如果一部分子元素相对于顶部对齐,一部分相对于底部对齐,是不会把 ConstraintLayout 撑到你的预期大小的。

你的布局方式应该改为始终相对于一个方向去对齐。

hackware1993 avatar Aug 02 '22 02:08 hackware1993

好的,谢谢您的解惑。

qflbai avatar Aug 02 '22 02:08 qflbai

钉在这里,供后面的小伙伴参考。

hackware1993 avatar Aug 02 '22 02:08 hackware1993

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,这时高度是计算不出来的吗?,导致界面啥也不显示。 1659412623376 0341229d98c0c59a3c1e6f6a5eb642d

qflbai avatar Aug 02 '22 03:08 qflbai

稍等我研究下

hackware1993 avatar Aug 02 '22 05:08 hackware1993

          ).applyConstraint(
            // id: idColumn,
            top: parent.top,
            // left: parent.left,
            height: wrapContent,
            width: matchParent,
            // width: matchConstraint,
            // right: parent.right,
          ),
        ],

改成这样就好了。宽度从 matchConstraint 改为 matchParent,删除横向的约束

hackware1993 avatar Aug 02 '22 05:08 hackware1993

这里牵扯到布局优先级的问题,整个 ConstraintLayout 中只有一个子元素,这里要指望 Column 把 ConstraintLayout 撑起来,那么 Column 的宽度就不能再是 matchConstraint,因为这样会让 parent 先布局,Column 后布局。这导致 parent 没有被任何元素撑起来,实际宽高为 0。就导致什么也展示不出来了 。我后面会写一篇原理分析的文章好好讲讲这些 “有坑” 的注意点。

hackware1993 avatar Aug 02 '22 06:08 hackware1993

约束布局的核心原理是按照优先级来布局,A 约束在 B 的右边,则 A 的布局优先级比 B 低。也就是要等 B 布局之后再布局 A。

你这里在横向上把宽高设为 matchConstraint,导致 Column 和 parent 产生了约束依赖关系,parent 的布局优先级高于 Column。因为要等 parent 的 left 和 right 确定以后,才能确定 Column 的宽度。

当你改用 matchParent 以后,横向上的约束依赖关系就被打破了,因为在布局 Column 时可以拿到 parent 的宽度,也就是 ListView 的宽度。这就使得 Column 可以先于 parent 布局,parent 就能被撑起来,界面展示就恢复正常了!

hackware1993 avatar Aug 02 '22 06:08 hackware1993

其实最主要的还是约束布局的约束推断算法不够聪明,不然你这么写也可以保证不出问题的

hackware1993 avatar Aug 02 '22 06:08 hackware1993

根据您的详细的回复,我解决了我项目中遇到的问题,谢谢您!

qflbai avatar Aug 02 '22 07:08 qflbai