你真的了解weight和weightSum嗎?

libingxue 8年前發布 | 27K 次閱讀 安卓開發 Android開發 移動開發

看到本文的標題,很多童鞋會一臉不屑的說,這有什么不了解的。不就是通過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

 

 本文由用戶 libingxue 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!