你真的了解weight和weightSum嗎?
看到本文的標題,很多童鞋會一臉不屑的說,這有什么不了解的。不就是通過weight來給子布局按比例來分配空間嘛!好,這個答案也對也不對。 此時有人會疑惑了,為什么也對也不對? 我先來舉兩個最常見的例子:
<?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="match_parent"
android:gravity="center"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="A" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="B" />
</LinearLayout>
<?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="match_parent"
android:gravity="center"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="A" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="B" />
</LinearLayout>
Paste_Image.png
這兩個例子都能實現上圖的效果。那么問題來了,這兩個方式有什么區別嗎? 眼尖的童鞋立馬會說:當然有區別,一個 android:layout_width 是0, 另一個是 wrap_content。 那么這兩個有什么區別嗎? 為什么實現的效果是一樣的? 我還要問一句,真的是一樣嗎?
如果對這個問題有所疑惑,那么兔子哥將帶領大家來深入了解一下weight和weightSum,并通過閱讀本篇文章,做到知其然,并且知其所以然。
什么是weight和weightSum
某位偉人曾經說過,要對某個知識點深入了解,最好的切入點就是仔細閱讀知識點的定義。至于這位偉人是誰,什么?想不起來了?不用想了,就是這篇博文的作者,兔子哥大人也! ~~~好了,扯了這么多廢話!我們還是先步入正題,先看看Google是怎么給 android:layout_weight 和 android:weightSum來定義的:
Layout Weight
LinearLayout also supports assigning a weight to individual children with the android:layout_weight attribute. This attribute assigns an "importance" value to a view in terms of how much space it should occupy on the screen. A larger weight value allows it to expand to fill any remaining space in the parent view. Child views can specify a weight value, and then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default weight is zero.
大體意思就是,android:layout_weight 這個屬性代表了一個“重要性”的值,這個值的大小代表了該控件能在屏幕中占據多大的空間。這個值越大,表明該控件可以在父控件中占據較多的“ 剩余 ”空間。默認的weight是0。
在這里,大家一定要注意“ 剩余 ”兩個字!大家往往容易忽略這一點,導致出現了很多問題。舉個例子:水平方向布局的父類有三個子類,父類總的寬度是100,子類的寬度分別是10,20,30。 那么 android:layout_weight 這個屬性的目的,就是瓜分剩余的 100 - 10 - 20 - 30,也就是剩余的40的使用權。沒錯! 就是android:layout_weight 這個屬性 僅僅決定 哪個子類能瓜分到更多的40的部分!
android:weightSum
Defines the maximum weight sum. If unspecified, the sum is computed by adding the layout_weight of all of the children.
這個就很好理解了,weightSum定義了weight 總和的最大值。如果 android:weightSum 沒有定義,那么默認值就是通過各個子類的 layout_weight 累加得到。
工作原理
講了這么多,舉個例子來說明一下。
<?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="match_parent"
android:gravity="center"
android:orientation="horizontal"
android:weightSum="1">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="@string/hello_world" />
</LinearLayout>
效果如下圖:
Paste_Image.png
內部的計算原理是:
Button的寬度 = Button 的 width + Button的weight * 父布局(LinearLayout)的寬度 / weightSum
上面的例子,也就是 Button的寬度 = 0 + 0.5 * LinearLayout的寬度 / 1 = 0.5 * LinearLayout的寬度
也就是Button的寬度將占屏幕的一半。
Google官方例子
結合上面的知識再看一下 Google的例子 ,可能體會的更加深刻。
首先看實現的效果:
Paste_Image.png
如果讓大家自己來實現這個效果的話,相信很多童鞋會采用相對布局,將send按鈕位于屏幕最下方,然后上面的三個EditText從上往下依次排列。但是message的EditText要鋪滿剩余的空間,這個怎么實現? 有的童鞋會不屑的說了,這有什么難的,把message的高度設置match_parent并且位于subject和send之間即可。代碼如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<EditText
android:id="@+id/et_to"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/to" />
<EditText
android:id="@+id/et_subject"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/et_to"
android:hint="@string/subject" />
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/btn_send"
android:layout_below="@id/et_subject"
android:gravity="top"
android:hint="@string/message" />
<Button
android:id="@+id/btn_send"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_gravity="right"
android:text="@string/send" />
</RelativeLayout>
但是如果采用本文講解的weight可能會更加的簡單。這個布局關鍵的一點是message要鋪滿subject與send之間的區域。問題是如何實現鋪滿呢? 對了! 本文講解的 weight 的核心就是瓜分父布局剩余的空間。全部瓜分不就是鋪滿嘛! 那么代碼也就出來了:
<?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="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:orientation="vertical" >
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/to" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/subject" />
<EditText
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top"
android:hint="@string/message" />
<Button
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="@string/send" />
</LinearLayout>
著重看一下message的布局:
<EditText
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top"
android:hint="@string/message" />
沒錯,采用了極為巧妙的方法。其他的子布局都不設置 layout_weight, 也就是默認是0 。 那么message將獲取全部的剩余空間,實現了鋪滿的效果。
后記
相信閱讀到這里的童鞋們,對文章開頭的問題應該已經知道答案了。如果還有童鞋不知道答案,可以試著將文章開頭的兩個Button的內容改一下,一個叫AAAAAAAAA,一個叫B。您再看一下效果,可能就明白了。至于那個也對也不對的問題,“不對”的原因是他們要瓜分的是 剩余 空間。本文止。
來自:http://www.jianshu.com/p/9b0407252e8b