layout_weight属性详解(源码解读)

来源:互联网 发布:程序员看招聘信息搞笑 编辑:程序博客网 时间:2024/04/29 13:34
在上一篇文章中《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
 
 如果觉得这篇文章对你有帮助,请点击下方的“”。大笑
 
16 0
原创粉丝点击