网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
Column(Modifier.fillMaxWidth()) {
Text(text = "hello world", Modifier.layout { measurable, constraints ->
// 可以理解为 传统view 中测量自己大小的步骤 获得自己宽高的尺寸
val placeable = measurable.measure(constraints)
// 拿到尺寸以后 就可以摆放自己的位置和大小了,大小就用测量出来的
layout(placeable.width, placeable.height) {
// 位置 就设置偏移量 即可
placeable.placeRelative(0, 0)
}
})
Text(
text = "hello world"
)
}
这里的2个Text 在实际展示上 位置和大小都一样,没有区别,放这个例子 其实就是为了给大家展示一下 layout的作用,实际上对于Modifer.size ,padding 等扩展函数 中,他们的内部实现 都是与这个layout 息息相关的
稍微分析一下上述的程序
由上图可知,我们传递进去的layout的lamda 他的返回值 必须得是 MeasureResult 这个接口类型的对象
可以看下这个接口, 他有宽高这2个我们熟悉的参数,还有 alignmentlines 这个有点像文字绘制时候的baseline的概念, 先跳过 不处理, 另外还有一个placeChildren的函数, 这个函数的作用 前面也提到过了,就是摆放自己的位置 ,这4个要素缺一不可,
回到我们开头的程序中
我们在lambda 内部调用的layout这个函数 注意看 他是属于measureScope的 不要和Modifier的layout搞混,这个 内部调用的layout函数,他默认帮我们返回了一个MeaureResult的对象, 方便就方便在这个对象 他默认帮我们实现了 alignmentLines 与 placeChildren函数
有人可能会疑惑 这里的 measure和layout和 传统自定义view的measure layout 好像啊,这里确实很像,但是细节上不是一个东西
比如说layout,传统自定义view中的layout 是专属于viewgroup的,你可以重写layout函数,摆放你所有子view的位置
而在compose的Modifier的layout中 你是无法摆放你子view的位置的
尝试在layout中完成padding的效果
我们有了第一小节的基础 就可以来尝试的完成 一个padding的效果
setContent {
Column(Modifier.fillMaxWidth()) {
Text(text = "hello world",
Modifier.background(Color.Yellow)
.layout { measurable, constraints ->
val padding = 10.dp.roundToPx()
// 可以理解为 传统view 中测量自己大小的步骤 获得自己宽高的尺寸
val placeable = measurable.measure(
constraints.copy(
maxWidth = constraints.maxWidth + padding * 2, maxHeight = constraints.maxHeight + padding * 2
)
)
// 拿到尺寸以后 就可以摆放自己的位置和大小了,大小就用测量出来的
layout(placeable.width + padding * 2, placeable.height * 2) {
// 位置 就设置偏移量 即可
placeable.placeRelative(padding, padding)
}
}
)
Text(
text = "hello world", modifier = Modifier.background(Color.Red)
)
}
}
LayoutModifier 对布局的影响
前面我们模仿了Modifier的padding实现,现在来看下 真正的padding 在compose中是如何做的
可以看到这里的关键是LayoutModifier接口
这里有人会问,在传统的view 体系中,是一个树形结构的view树,那在compose中是啥? 在compose中也是一个树形结构, 但是那不是view树了,而是一个LayoutNode树
在传统view体系中,通常是measure和layout 来相互配合 最终渲染出我们想要的结果,同样的,在LayoutNode中 也有类似的函数 remeasure 与 relayout
可以一步步跟一下核心的代码
这个measure方法 是个interface方法
他的具体实现其实就是
注意这里的实现类是InnerPlaceable ,我们后面还会再遇到他
这个measureResult 也就是测量结果 就会在布局的流程中 调用
了解了大概的measure流程,我们就可以开始分析一下 LayoutModifier到底对Compose的界面绘制有什么作用?
那么多的LayoutModifier 比如padding,size等等,他们的先后顺序 对Compose的界面绘制影响如何?
我们首先可以关注一下LayoutNode的 modifier这个属性
尤其是他的set方法, 这个就很关键了,我们每次给一个compose的组件 设置他的 modifier属性的时候 都会走到这个方法里面
仔细看一下这个函数,关键点在红框内:
我们首先看一下这个foldout函数,他的意思就是 把modifier这个链表,从右到左 进行遍历
怎么理解这句话
看下面的使用方法,所谓从右到左遍历,就是先读background 然后读padding 最后读fillmaxwidth
再看第二个红框中的代码:
这里我们首先关注那个最大的红框,这里其实就是当判断了mod 是layoutModifier以后 就会走这个大红框的逻辑
大红框的逻辑很简单,其实就是 创建一个ModifidLayoutNode 或者 重用之前的ModifidLayoutNode
这个mod是啥?这个mod就是我们设置的哪些LayoutModifier,
towrap是啥? 诶,这个地方就很关键了,我们之前提过,这里的遍历是从右往左进行遍历, 这个towrap
就是之前那次遍历的结果, 这个看一下这个lambda的最后表达式就很清楚了
有人这里就要问了,towrap 是之前那次遍历的结果,那第一次遍历呢? 第一次遍历
怎么取之前的遍历结果?
其实对于第一次遍历来说,这个towrap的值就是foldOut的参数 这个inneraLayoutNodeWrapper
他其实就是InnerPlaceable
InnerPlaceable 这个其实就是之前我们读过的代码 负责measure的
所以我们理解这段代码以后 他的含义就是
从右往左来遍历这个modifier,对于layoutModifier来说,最右边的在最里面,最左边的在最外面,
再换句话说,
如果我们写了一个Compose的组件,比如是一个Text组件,
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
)]
[外链图片转存中…(img-2lqimwdS-1715742120133)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新