Android之layout_weight解析
我们先来看以下这段Android布局代码:
1 <LinearLayout 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <TextView 7 android:layout_width="0.0dip" 8 android:layout_height="100.0dip" 9 android:layout_weight="1" 10 android:background="@color/colorAccent" 11 android:gravity="center" 12 android:text="1111111111111111111" 13 android:textColor="@color/black" 14 android:textSize="18.0sp" 15 android:textStyle="bold"/> 16 17 <TextView 18 android:layout_width="0.0dip" 19 android:layout_height="100.0dip" 20 android:layout_weight="2" 21 android:background="@color/colorPrimary" 22 android:gravity="center" 23 android:text="2" 24 android:textColor="@color/black" 25 android:textSize="18.0sp" 26 android:textStyle="bold"/> 27 28 <TextView 29 android:layout_width="0.0dip" 30 android:layout_height="100.0dip" 31 android:layout_weight="3" 32 android:background="@color/white" 33 android:gravity="center" 34 android:text="3" 35 android:textColor="@color/black" 36 android:textSize="18.0sp" 37 android:textStyle="bold"/> 38 39 </LinearLayout>
在线性布局LinearLayout中,三个TextView以layout_weight属性分别是1、2、3来布局,它们的高度都是100dip,宽度都是0dip。在这种情况下,三个TextView的布局是什么样子的呢?答案如下图所示。
如上图所示,三个TextView所占的宽度分别是1:2:3,这是在我们意料之中的,在我们意料之外的是,第一个TextView的位置偏下。这是为什么呢?我们只需要对结果图稍作处理,答案就会显而易见,见下图。
如上图所示,我们加上一道“辅助线”之后就会发现,虽然位置参差不齐,但它们的第一行文本的位置是在同一高度的。由此我们得出结论:在Android的LinearLayout布局中,TextView默认是根据第一行文本来对齐的。可是我们怎样消去这种文本对齐关系呢?我们只需要在父布局的LinearLayout中添加这样一句代码 android:baselineAligned="false" 就可以解决这个问题,解决后的布局图如下:
如果我们把某一个TextView的layout_width属性设置为wrap_content,结果又会如何呢?如果我们将上面的布局代码修改成如下的样子,那么我们会得到如下图所示的结果。
1 <LinearLayout 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:baselineAligned="false"> 6 7 <TextView 8 android:layout_width="wrap_content" 9 android:layout_height="100.0dip" 10 android:layout_weight="1" 11 android:background="@color/colorAccent" 12 android:gravity="center" 13 android:text="1111111111111111111" 14 android:textColor="@color/black" 15 android:textSize="18.0sp" 16 android:textStyle="bold"/> 17 18 <TextView 19 android:layout_width="0.0dip" 20 android:layout_height="100.0dip" 21 android:layout_weight="2" 22 android:background="@color/colorPrimary" 23 android:gravity="center" 24 android:text="2" 25 android:textColor="@color/black" 26 android:textSize="18.0sp" 27 android:textStyle="bold"/> 28 29 <TextView 30 android:layout_width="0.0dip" 31 android:layout_height="100.0dip" 32 android:layout_weight="3" 33 android:background="@color/white" 34 android:gravity="center" 35 android:text="3" 36 android:textColor="@color/black" 37 android:textSize="18.0sp" 38 android:textStyle="bold"/> 39 40 </LinearLayout>
我们把第一个TextView的宽度属性设置成wrap_content,结果如上图所示。从结果中我们可以看到,我们得到的结果不符合1:2:3的布局比例。这时为什么呢?这时因为,Android会先分配已经声明尺寸的控件的空间,再分配未声明尺寸的控件的空间。在这个例子中,第一个TextView的宽度已经声明(wrap_content),而另外两个TextView的宽度都是0(等待父布局按layout_weight分配),那么Android就会先分配第一个TextView的空间,然后再把剩余的空间按1:2:3的比例分配给三个TextView。
如果三个TextView的宽度都是已经声明的,结果又会是怎样的呢?我们把三个TextView的宽度比例改成1:2:2,并把它们的宽度都设置成match_parent(代码如下),这样,我们就会得到如下图所示的结果。
1 <LinearLayout 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:baselineAligned="false"> 6 7 <TextView 8 android:layout_width="match_parent" 9 android:layout_height="100.0dip" 10 android:layout_weight="1" 11 android:background="@color/colorAccent" 12 android:gravity="center" 13 android:text="1111111111111111111" 14 android:textColor="@color/black" 15 android:textSize="18.0sp" 16 android:textStyle="bold"/> 17 18 <TextView 19 android:layout_width="match_parent" 20 android:layout_height="100.0dip" 21 android:layout_weight="2" 22 android:background="@color/colorPrimary" 23 android:gravity="center" 24 android:text="2" 25 android:textColor="@color/black" 26 android:textSize="18.0sp" 27 android:textStyle="bold"/> 28 29 <TextView 30 android:layout_width="match_parent" 31 android:layout_height="100.0dip" 32 android:layout_weight="2" 33 android:background="@color/white" 34 android:gravity="center" 35 android:text="3" 36 android:textColor="@color/black" 37 android:textSize="18.0sp" 38 android:textStyle="bold"/> 39 40 </LinearLayout>
按照我们上一个demo得到的结论,Android先分配已经声明的控件的空间,那么这里,这三个TextView的宽度应该是按照1:2:2的比例分配的,即把屏幕宽度分成五份,然后让这三个TextView分别占一份、两份、两份。但现在为什么得到的结果与理论不相同呢?其实,我们得到的结果正是“一丝不苟”的按照我们得到的理论进行的,下面我们来分析一下。
我们假设手机屏幕的宽度是480dip,那么按照我们之前得出的结论(先给已经声明的控件分配空间),这三个TextView的宽度都应该是480dip(和屏幕的尺寸相同),那么剩余的空间就是480-(480*3)=-960,也就是说,我们要把-960dip评分成五份,然后按照1:2:2的比例分配给三个TextView。那么,第一个TextView就会分配到-192dip,第二个和第三个TextView都分配到-384dip。用它们之前分配的和屏幕同样宽度的480dip分别减去它们后来分配的尺寸,就可以求出它们实际所占的尺寸分别是288dip、96dip和96dip,即3:1:1。
layout_weight还有一个非常有用的作用,我们来看下面这个需求:我们想要得到一个占屏幕二分之一的TextView,我们该怎么办呢?这时,我们就可以利用layout_weight来解决这个问题。代码如下,结果如下图所示。
1 <LinearLayout 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:weightSum="2"> 6 7 <TextView 8 android:layout_width="0.0dip" 9 android:layout_height="100.0dip" 10 android:layout_weight="1" 11 android:background="@color/colorAccent" 12 android:gravity="center" 13 android:text="1111111111111111111" 14 android:textColor="@color/black" 15 android:textSize="18.0sp" 16 android:textStyle="bold"/> 17 18 </LinearLayout>