在上一篇文章中《View工作原理(三)视图大小计算过程(measure过程) 》,我们详细的介绍了View的measure过程,我在讲解LinearLayout的measure过程中,提到了layout_weight这个属性,今天就来详细介绍下这个属性。如果要完全理解这篇文章,建议先看看前一篇文章。
这里我们还是以LinearLayout的纵向布局来分析,即measureVertical()方法。
父视图在对子视图进行measure操作的过程中,使用变量mTotalLength保存已经measure过的child所占用的高度,该变量刚开始时是0。在for循环中调用measureChildBeforeLayout()对每一个child进行测量,该函数实际上仅仅是调用了measureChildWithMargins(),在调用该方法时,使用了两个参数。其中一个是heightMeasureSpec,该参数为LinearLayout本身的measureSpec;另一个参数就是mTotalLength,代表该LinearLayout已经被其子视图所占用的高度。
每次for循环对child测量完毕后,调用child.getMeasuredHeight()获取该子视图最终的高度,并将这个高度添加到mTotalLength中。
在本步骤中,暂时避开了lp.weight>0的子视图,即暂时先不测量这些子视图,因为后面将把父视图剩余的高度按照weight值的大小平均分配给相应的子视图。源码中使用了一个局部变量totalWeight累计所有子视图的weight值。处理lp.weight>0的情况需要注意,如果变量heightMode是EXACTLY,那么,当其他子视图占满父视图的高度后,weight>0的子视图可能分配不到布局空间,从而不被显示,只有当heightMode是AT_MOST或者UNSPECIFIED时,weight>0的视图才能优先获得布局高度。下面我们通过例子来说明这一问题。
布局一:activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dp"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_weight="2"
android:gravity="center"
android:background="@color/main_bar_1"
android:textSize="20sp"
android:text="tv1" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/main_bar_2"
android:gravity="center"
android:textSize="20sp"
android:text="tv2" />
</LinearLayout>
效果图如下:
![[置顶] layout_weight属性详解(源码解读)_第1张图片](http://img.e-com-net.com/image/info5/6aeaeb5697a8473fa8f0a6d2b3cae075.jpg)
解释:父视图的高度是200dp,tv1的高度是300dp,tv2的高度是200dp,按照常理,应该是先给tv1进行布局,显示的应该是tv1才对。但是tv1设置了layout_weight="2",所以在进行measure操作时,先对tv2的高度进行计算,先给它分配空间,真好它的高度和父视图的高度相同,所以tv1没有显示的空间了。
布局二:activity_main2.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_weight="2"
android:gravity="center"
android:background="@color/main_bar_1"
android:textSize="20sp"
android:text="tv1" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/main_bar_2"
android:gravity="center"
android:textSize="20sp"
android:text="tv2" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/main_bar_3"
android:gravity="center"
android:textSize="20sp"
android:text="tv3" />
</LinearLayout>
效果图如下:
![[置顶] layout_weight属性详解(源码解读)_第2张图片](http://img.e-com-net.com/image/info5/dfae6f3ab50d413e9cecf2c7013bb35c.jpg)
解释:父视图充满全屏,tv1的高度是100dp,tv2的高度是200dp,tv3的高度是100dp。但是显示却没有按照这个比例来。measure过程是:先计算tv2,和tv3的高度,发现他们的高度没有填没父视图,所以在计算tv1的高度,累加之后还是没有填满父视图,所以将剩下的空间平均分配给设置layout_weight属性的子视图,即分配给了tv1.
布局三:activity_main2.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="400dp"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_weight="1"
android:gravity="center"
android:background="@color/main_bar_1"
android:textSize="20sp"
android:text="tv1" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/main_bar_2"
android:gravity="center"
android:textSize="20sp"
android:text="tv2" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/main_bar_3"
android:gravity="center"
android:textSize="20sp"
android:text="tv3" />
</LinearLayout>
效果图如下:
![[置顶] layout_weight属性详解(源码解读)_第3张图片](http://img.e-com-net.com/image/info5/39bab5af785249b59740788791053402.jpg)
解释:父视图的高度是400dp,tv1的高度是100dp,tv2的高度是0dp,tv3的高度是0dp。他们相应的weight比重是1:1:1。父视图在measure的过程中,首先进行避开lp.weight>0的子视图,发现他们三个都被避开了,接着进行高度lp.weight>0的高度累计,发现tv1的高度是100dp,所以首先给tv1分配100dp的高度,然后剩下的区域进行平均分配,所以,显示的结果是:tv1=200dp,tv2=100dp,tv3=100dp。
转载请说明出处:http://blog.csdn.net/ff20081528/article/details/17582787
布局三:activity_main3.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="400dp"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:background="@color/main_bar_1"
android:textSize="20sp"
android:text="tv1" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/main_bar_2"
android:gravity="center"
android:textSize="20sp"
android:text="tv2" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/main_bar_3"
android:gravity="center"
android:textSize="20sp"
android:text="tv3" />
</LinearLayout>
效果图如下:
![[置顶] layout_weight属性详解(源码解读)_第4张图片](http://img.e-com-net.com/image/info5/dfc71596b4d74565811d5fd155e0b8bf.jpg)
这个结果,我想不用解释了吧!
demo:http://download.csdn.net/detail/ff20081528/6772659
如果觉得这篇文章对你有帮助,请点击下方的“顶”。![大笑](http://img.e-com-net.com/image/info5/b1935790f5754d67a23ef51b74fcc8fd.gif)