layout_weight属性详解(源码解读)

	在上一篇文章中《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>

 效果图如下:
 
 解释:父视图的高度是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>

 效果图如下:
解释:父视图充满全屏,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>

 效果图如下:
解释:父视图的高度是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>

效果图如下:
这个结果,我想不用解释了吧!
demo:http://download.csdn.net/detail/ff20081528/6772659
 
 如果觉得这篇文章对你有帮助,请点击下方的“”。大笑
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值