View.onMeasure()

问题:Android是如何确定View大小的?


width和height是独立的,可以分开考虑,所以我们只关注width;

假设:

1)我们先自定义三个View A,B,C,全部继承自LinearLayout;

2)我们的测试机的屏幕宽度是1080;


实验1, 如果全部跟着父控件走:


<A with=“match_parent">

   <B  with="match_parent'>

         <C witdh="match_parent"

        </C>

   </B>

</A>


则执行顺序是:

A EXACTLY 1080 (A的上级是1080宽度,而A的愿望是match_parent, 所以上级给A的spec就是EXACTLY 1080)

B EXACTLY 1080 (A的spec是EXACTLY 1080, B自己的愿望是match_parent,所以A给B的spec就是EXACTLY 1080)

C EXACTLY 1080 (B的spec是EXACTLY 1080, 而C自己的愿望是match_parent, 所以B给C的spec就是EXACTLY 1080)

C.width = 1080 (C的spec是EXACTLY 1080,  于是宽度就确定为1080)

B.width = 1080 (C的spec是EXACTLY 1080,  于是宽度就确定为1080)

A.width = 1080(C的spec是EXACTLY 1080,  于是宽度就确定为1080)

spec从上往下传递,而最终size的确定顺序是从下往上的;


实验2,如果全部跟着子控件走:

<A with="wrap_content">

   <B  with="wrap_content'>

        <C witdh="wrap_content"

        </C>

   </B>

</A>


则执行顺序是:

A AT_MOST 1080(A的上级是1080的,而A想包含内容,所以上级就规定A最多1080宽)

B AT_MOST 1080 (A最多1080,而B想包含内容,所以A规定B最多1080宽)

C AT_MOST 1080 (B最多1080,而C想包含内容,所以B规定C最多1080宽)

C.width = 0 (C的spec是AT_MOST 1080, 而C作为LinearLayout的子类,由于没有内容,所以决定取0,其实这儿C只要不超过1080,可以随便取值的)

B.width = 0 (B的spec是AT_MOST 1080, 而C已经确定为0,为了wrap C,B可以取0到1080之间的任意值,这儿实际取值0,注意B既考虑了第一遍从上而下传过来的spec,也考虑了child的宽度)

A.width = 0 (A的spec是AT_MOST 1080, 而B已经确定为0,为了wrap B,A可以取0到1080之间的任意值,这儿实际取值0)


实验3,parent让child定,child让parent定,简单点,2级就能说明问题:

<A with="wrap_content">

   <B  with="match_parent'>

   </B>

</A>


则执行顺序是:

A AT_MOST 1080(A的上级是1080的,而A想包含内容,所以上级就规定A最多1080宽)

B AT_MOST 1080 (A最多1080,而B想跟parent也一样大,由于A此时只知道不超过1080,并没有确定具体的值,所以A也只能规定B最多1080)

B.width = 0 (B的spec是AT_MOST 1080,  所以可以在0到1080任意取值,实际取值0)

A.width = 0 (A的spec是AT_MOST 1080, 而B已经确定为0,为了wrap B,A可以取0到1080之间的任意值,这儿实际取值0)



规律:

1)spec从上往下传递,而最终size的确定顺序是从下往上的;

2)第一遍是从上往下走,每个parent根据自己的spec,结合child的parameter,计算出给child的spec;

第二遍从下往上确定大小,每个child应该尊重parent给的spec,当然了,如果你非要违反,也没问题,等轮到parent决定大小的时候,可以根据child的实际大小见机行事,比如当child超过自己的时候引入滚动;

每个parent在决定大小的时候,既要考虑第一轮传下来的spec,也要考虑child已经确定好的大小,至于如何根据child的大小行事,就看你怎么实现onMeasure()方法 了,

通常默认的onMeasure()实现不是你想要的效果;

3)wrap_content应该了解为大于等于,而不是等于,只要能包含child就可以;

4)UNSPECIFIED在我们的例子里都没出现,这种spec估计是用在ScollView或者ListView里(height上),parent完全不给child任何的约束,child想多大就多大;






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值