Anroid深度核析: P305
因为fillParent和wrapContent导致各种权重产生不同的效果.之前也一直没有从底层搞清.今天看了书后正好涉及到权重,于是查了下网上资料并总结下
网上资料:http://blog.youkuaiyun.com/chuxing/article/details/7091862
首先权重只存在于LinearLayout中,其他布局无效.所以针对LinearLayout的onMeasure()过程进行解析
( View系统的onMeasure()过程必须由相应的ViewGroup实例共同参与才能完成一个真正的measure操作 )
view中的measure()是无法被重载的以保证View系统的measure()基本流程.ViewGroup的实例一般需要重载onMeasure()并在函数中调用measureChild()对每一个子View进行操作.
LinearLayout会进行两次measure,
第一次会计算weight为0的子View所要占据的面积
第二次会把第一次之后剩余的面积分配给weight>0的子View.(如果没有剩余面积了,则这些weight>0的子view将不显示)
布局①:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dip"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="50dip"
android:text="1111111111111"
android:layout_weight="1"
/>
<TextView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="222222222222222"
></TextView>
</LinearLayout>
效果图:
先将2显示出来 多余的部分显示给1 其中给1设置的50dip也是无效的.因为权重让系统将剩余部分自动全部分配给了1
如果将2改为 match_parent
则效果图为:
因为2没权重,所以第一次measure会先给2分配空间.当第二次measure的时候1就没有空间了.所以不显示.
如果在上一步的基础上把1的权重去掉:
这个时候2会填充剩下的布局
如果在上一步的基础上把2改为wrapContent:
布局②
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dip"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="50dip"
android:text="1111111111111"
android:layout_weight="1"
/>
<TextView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:text="222222222222222"
></TextView>
</LinearLayout>
效果图:
LinearLayout先给2赋高度然后将剩下的给1
在上面的基础上,给2也加上weight=1
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dip"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="50dip"
android:text="1111111111111"
android:layout_weight="1"
/>
<TextView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:text="222222222222222"
android:layout_weight="1"
></TextView>
</LinearLayout>
效果图:
可以看出,系统先给1分配了50dip然后剩余的给了2 (此时2的0dip无效,后来改成50dip 这个时候 1
和 2 平分区域)
将1 2 都改成 matchparent
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dip"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="1111111111111"
android:layout_weight="1"
/>
<TextView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="222222222222222"
android:layout_weight="1"
></TextView>
</LinearLayout>
如果当把1的权重加大则会减少1的显示范围: 假设1的权重为1K 2为1 则
因为根据公式
第二次:计算delta=x-total_width=-x,然后会将button1的宽度设为
x+delta*1/3=0.66x, button2的宽度为 x+delta*2/3=0.33x
此时1的显示为 X-X*(1000/1001)=1/1000 显示剩余空间千分之一的面积
2显示为 X-X*(1/1000)=999/1000 显示剩余面积的999/1000
对应布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dip"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="1111111111111"
android:layout_weight="10000000000"
/>
<TextView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="222222222222222"
android:layout_weight="1"
></TextView>
</LinearLayout>
效果图:
2的权重较小所以先加载2,2的高度几乎要填满父布局了,虽然看不到1的显示 但是实际上还是占有位置的
在上面的基础上将2改为wrapcontent
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dip"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="1111111111111"
android:layout_weight="10000000000"
/>
<TextView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="222222222222222"
android:layout_weight="1"
></TextView>
</LinearLayout>
此时效果图为:
2的权重小,先加载2,这个时候2为wrap_content 所以会尽量小,最小是wrap_content.然后再把剩余部分给1
如果在上面的基础上把1也改成 wrapcontent 那么还是如上的显示效果图. 原因也跟上面一样
布局③:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dip"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="100dip"
android:text="1111111111111"
android:layout_weight="1"
/>
<TextView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:text="222222222222222"
android:layout_weight="1"
></TextView>
</LinearLayout>
效果图如下
由于2此时的高度为0dip,所以仅仅是share剩余的高度,此时1和2的权重也一样,所以先加载1,先给了1 100dip,然后剩余部分1和2平分
,于是又给了1 50dip也给了2 50dip.这个时候1占据了150dip 2只有50dip
如果这个布局改变1的height>=200dip 则2将无法显示在视图上