Jetpack Compose的Modifier顺序问题

一:前言

困惑起源于这段代码

Composable.clickable(点击1).clickable(点击2).size(100.dp).size(200.dp){
...............
}

Composable是随便一个@Composable函数。结果是:点击二会应用,size100dp会应用。

一开始,我试验size的时候,以为是modifier从右往左应用的,但clickable的处理显然违背了这个事实,再放多一个实例

Text("Hi there!", Modifier.padding(10.dp).border(2.dp, Color.Magenta))

这是一个stack overflow的问题,显示结果如下:

Jetpack Compose的Modifier顺序问题

 

 

 他因此疑惑,modifier应该是从右往左应用的吧,先border,再padding,十分合理。

 

二:先上结论

  • modifier的应用既不是从左往右,也不是从右往左,而是从左往右,然后从右往左回来
  • modifier有很多种类,既有控制触摸的pointer modifier,也有border的draw modifier,也有padding/size这些layout modifier
  • layout modififier和其他modifier的处理都不一样,layout modifier会从左往右传递constraint,又从右往左传递size回来。也就是说,layout modifier是左到右,然后右到左走两遍,其他modifier是从右到左只走一遍
  • constraint是约束的意思,类似于view系统中的MeasureSpec,不过constraint做的更多,可以抽象成拥有四个参数,最小宽,最大宽,最小高,最大高。左边的layout modifier把constraint 传给右边的layout modifier,右边的layout modifier测量之后,把尺寸信息传给左边。
  • layout modifier都有一个measure方法用来测量大小。

 

三:上示例解释

Box(modifier = Modifier.height(200.dp).width(250.dp)){
        Text("Hello, honey?",
            Modifier
                .fillMaxSize()
                .padding(10.dp)
                .size(100.dp)
                .border(1.dp, Color.Black)
                .size(200.dp))
    }

最外面的box仅仅起到一个控制范围的作用,不要考虑,我们要做的是分析这个text的modifier。

开始喽!!!

Jetpack Compose的Modifier顺序问题

 

 

1: 首先,最外面的Box给到第一个modifier 约束,如图所示。

2:fillmaxsize会把约束都撑大,因此它测量下一个modifier给到的约束是min max都为一个固定最大值。

3:padding收到约束,因为它需要四周留空。这里插一个小知识,modifier是针对当前composable自身的,和content无关。因此padding考虑它自身一定要留空那么多padding,所以它会像一个吝啬地主那样,把钱克扣很多之后,才给它下面的员工。因此它把约束都减掉2 * padding。图中画错了,因该是230 和 180.

4: size收到约束,它一看,你TM给我那么多空间吗!!太好了吧!!可是我不需要那么多,我只需要100,我把约束设为100,然后传给下一个。

5:border不是layout modifier不会对约束处理,它是从右往左的时候才会应用的。直接把约束传过去。

6:size200对于上面把约束固定死了的,无能为力,继续传100.

7:  最后,整个text收到100 x 100的信息,它就把自己size设为100 x 100,然后把size信息(蓝色部分)传上去

6:size200不更改这个100 x 100的size信息,继续传上去

5:size信息传到border这里,添加了border信息。

4:传到size100这里,继续把size信息传上去

3:padding加上约束,size变为120 x 120, 这里注意啦,先添加的border信息,再添加的padding信息!!!,这解释了stack over flow那个问题。

2:120 x 120传到fillmaxsize这里,它很霸道啊,利用下面传上来的信息测得最终大小竟然是250 x 200。

1:Box get it!!心领神会!!

 

备注: 在从左往右的时候,是约束constraint的传递,会跳过非layout modifier。layout modifier可能修改约束,也可能不修改约束。从右往左的时候,在layout modifier之间传递的,是右边的modifier测得的size大小信息,以及如何摆放等信息,遇到非layout modifier,会添加额外信息!!

 

 

四: 源码上

主要涉及LayoutNode,过几天补充。

 

 

参考资料:

https://www.youtube.com/watch?v=zMKMwh9gZuI&t=1043s&ab_channel=AndroidDevelopers

https://developer.android.com/codelabs/jetpack-compose-layouts#8

星标:https://*.com/questions/64206648/jetpack-compose-order-of-modifiers

https://joebirch.co/android/exporing-jetpack-compose-padding-modifier/

 

上一篇:DC-2


下一篇:yum安装过程 保留安装包