First child: “OK,那我想要 290 像素的宽度,20 个像素的长度。”

Widget: “嗯…由于我想要将我的第二个子级放在第一个子级下面,所以我们仅剩 55 个像素的高度给第二个子级了。”

Widget: “嘿,我的第二个子级,你的宽度必须要在 0290,长度在 055 之间。”

Second child: “OK,那我想要 140 像素的宽度,30 个像素的长度。”

Widget: “很好。我的第一个子级将被放在 x: 5 & y: 5 的位置,而我的第二个子级将在 x: 80 & y: 25 的位置。”

Widget: “嘿,我的父级,我决定我的大小为 300 像素宽度,60 像素高度。”

什么是约束?

====================================================================

约束Constraints 在Flutter中是一种_布局协议_,Flutter中有两大布局协议BoxConstraintsSliverConstraints。对于非滑动的控件例如Padding,Flex等一般都使用_BoxConstraints盒约束_。

约束可以分为:宽松约束(loose)和 严格约束(tight) 就widget布局树而言,约束默认向下传递,可有些布局类复写了performLayout改变了约束行为,将向下传递的约束信息改变甚至重建,从而导致有些布局行为变得不可预测,因此就需要掌握一些常用布局的布局原理,才能对整体的布局行为加以分析。

案例分析


案例一:Container的约束失效

ConstrainedBox(

constraints: BoxConstraints.tightFor(

width: double.infinity,

height: double.infinity),

child: Container(width: 100, height: 100, color: red)

)

上边的案例,展示了一个预期宽100,高100的红色方块,可实际上只会得到一个满屏幕的红色。 虽然Container内部有宽高的约束,但是在这里是不起作用的,究其原因,是因为Container内部的布局特性引起的,父部件传递一个tight紧布局,而到了Container由于内部使用的ConstrainedBox,其布局行为会做如下改变:

@override

// this.constraints 为父部件传递的约束

void performLayout() {

final BoxConstraints constraints = this.constraints; // this.constraints为父部件传递过来的约束

if (child != null) {

// 在这里改变了约束,可能会导致自身设置的约束失效

child!.layout(_additionalConstraints.enforce(constraints),

parentUsesSize: true);

size = child!.size;

} else {

size = _additionalConstraints.enforce(constraints).constrain(Size.zero);

}

}

// clamp方法会自行在约束范围境内选择

BoxConstraints enforce(BoxConstraints constraints) {

return BoxConstraints(

minWidth: minWidth.clamp(constraints.minWidth, constraints.maxWidth),

maxWidth: maxWidth.clamp(constraints.minWidth, constraints.maxWidth),

minHeight: minHeight.clamp(constraints.minHeight, constraints.maxHeight),

maxHeight: maxHeight.clamp(constraints.minHeight, constraints.maxHeight),

);

}

按照先前的布局原理来说,Container告诉父布局自己需要一个100x100的空间,而父布局也有充分的空间提供,那预期的效果应该会很好的呈现,可在这里由于ConstrainedBox内部改变了布局行为,导致预期结果不生效,ConstrainedBox会通过enforce函数衡量自身的约束属性即 _additionalConstraints,和父布局传递的约束,在其中取临近值,在这里由于父部件约束为:

BoxConstraints(

minWidth: double.infinity,

maxWidth: double.infinity,

minHeight: double.infinity,

maxHeight: double.infinity,

);

故所以_additionalConstraints的约束行为会被改成double.infinity~double.infinity之间的值即double.infinity。

案例二:奇怪的LimitedBox

现有这样两个场景:

ConstrainedBox(

constraints: BoxConstraints.tightFor(

width: double.infinity,

height: double.infinity),

child: UnconstrainedBox(

child: LimitedBox(

maxWidth: 100,

child:

Container(color: Colors.red, width: double.infinity, height: 100),

),

)

)

ConstrainedBox(

constraints: BoxConstraints.tightFor(

width: double.infinity,

height: double.infinity),

child: Center(

child: LimitedBox(

maxWidth: 100,

child:

Container(color: Colors.red, width: double.infinity, height: 100),

),

)

)

两者的区别不是很明显,只是前者的LimitedBox由UnconstrainedBox包裹,而后由Center包裹,但两个例子所展示的UI却大相径庭:

这样看来是Center致使LimitedBox的maxWidth约束失效了,为什么会这样呢?

// LimitedBox的布局过程

BoxConstraints _limitConstraints(BoxConstraints constraints) {

return BoxConstraints(

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

总结

可以看出,笔者的工作学习模式便是由以下 「六个要点」 组成:

❝ 多层次的工作/学习计划 + 番茄工作法 + 定额工作法 + 批处理 + 多任务并行 + 图层工作法❞

希望大家能将这些要点融入自己的工作学习当中,我相信一定会工作与学习地更富有成效。

下面是我学习用到的一些书籍学习导图,以及系统的学习资料。每一个知识点,都有对应的导图,学习的资料,视频,面试题目。

**如:我需要学习 **Flutter的知识。(大家可以参考我的学习方法)

点击这里了解更多即可领取!
  • Flutter 的思维导图(无论学习什么,有学习路线都会事半功倍)

  • Flutter进阶学习全套手册

  • Flutter进阶学习全套视频

点击这里了解更多即可领取!

  • Flutter 的思维导图(无论学习什么,有学习路线都会事半功倍)

[外链图片转存中…(img-pzsyrVAo-1710658875770)]

  • Flutter进阶学习全套手册

[外链图片转存中…(img-Rw658YcJ-1710658875771)]

  • Flutter进阶学习全套视频

[外链图片转存中…(img-s27KQVMA-1710658875771)]

大概就上面这几个步骤,这样学习不仅高效,而且能系统的学习新的知识。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐