【轉(zhuǎn)】深入了解layout_weight屬性

深入了解layout_weight屬性

前言

Android中l(wèi)ayout_weight這個(gè)屬性對(duì)于經(jīng)常搗鼓UI的我們來(lái)說(shuō),肯定不會(huì)陌生。但是我們?cè)谡嬲褂眠@個(gè)屬性時(shí),經(jīng)常會(huì)出現(xiàn)一些莫名奇妙的布局效果;如果僅僅知其然而不知其所以然,一些意外的布局效果一定讓我們頗為頭疼。在本文中,將對(duì)layout_weight這個(gè)屬性詳細(xì)剖析。

正文

從代碼講起:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
                    android:layout_width="match_parent" 
                    android:layout_height="match_parent" 
                    android:orientation="vertical"> 
    <Button 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:text="button1" /> 
    <Button 
        android:layout_width="match_parent"     
        android:layout_height="wrap_content" 
        android:text="button2" /> 
    <Button 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:text="button3" />
</LinearLayout>

效果圖如下:


我們可以發(fā)現(xiàn)這三個(gè)button并沒(méi)有將整個(gè)屏幕占據(jù),而是根據(jù)內(nèi)容適配大小。
我們?cè)赽utton2里面添加一個(gè)屬性 android:layout_weight="1" ,發(fā)現(xiàn)布局變成這樣了:

我們發(fā)現(xiàn)這次屏幕被三個(gè)button占據(jù)了,而且第一個(gè)和第三個(gè)button還是保持與內(nèi)容適配大小,而第二個(gè)button而占據(jù)了剩余屏幕空間。

我們對(duì)上面的情況進(jìn)行講解:
1、我們只有在button2使用了layout_weight屬性,并賦值為1;但是button1和button2并沒(méi)有使用這個(gè)屬性,根據(jù)API可以知道,他們的layout_weight屬性等于0。
2、LinearLayout如果顯式包含layout_weight屬性時(shí),會(huì)measure兩次;第一次將正常計(jì)算三個(gè)button的寬高,第二次將結(jié)合layout_weight的值分配剩余的空間。

通俗點(diǎn)來(lái)總結(jié):Android系統(tǒng)先按照你設(shè)置的3個(gè)Button高度Layout_height=wrap_content,給你分配好他們3個(gè)的高度。
然后會(huì)把剩下來(lái)的屏幕空間全部賦給Button2。因?yàn)橹挥兴臋?quán)重值是1,這也是為什么Button2占了那么大的一塊空間。
這么講解大概大家也對(duì)layout_weight屬性有了比較清晰的認(rèn)識(shí)了吧。

再來(lái)看看下面的代碼:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
                    android:layout_width="match_parent" 
                    android:layout_height="match_parent" 
                    android:orientation="horizontal"> 
    <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_weight="1" android:text="1" 
        android:background="#ff0000" /> 
    <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_weight="2" android:text="2" 
        android:background="#00ff00" /> 
    <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_weight="3" android:text="3" 
        android:background="#0000ff" />
</LinearLayout>

在我們對(duì)這三個(gè)TextView的layout_width都設(shè)置為wrap_content時(shí),我們會(huì)得到以下布局:


這個(gè)布局很符合我們上面的分析:
系統(tǒng)先給3個(gè)TextView分配他們的寬度值wrap_content(寬度足以包含他們的內(nèi)容1,2,3即可),然后會(huì)把剩下來(lái)的屏幕空間按照1:2:3的比列分配給3個(gè)textview,所以就出現(xiàn)了上面的圖像。
如果我們將上面三個(gè)TextView的layout_width都設(shè)置為match_parent,分別給三個(gè)TextView設(shè)置他們的Layout_weight為1、2、2的話,會(huì)出現(xiàn)一個(gè)相反的布局效果:

我們大概可以分辨出,他們所占的寬的比例為3:1:1。這樣就出現(xiàn)一個(gè)另外一個(gè)效果:weight權(quán)重越大,控件所占的空間越小。

所以網(wǎng)上就有人這么總結(jié)
在layout_width設(shè)置為match_parent的時(shí)候,layout_weight所代表的是你的控件要優(yōu)先盡可能的大,但這個(gè)大是有限度的,即match_parent。
在layout_width設(shè)置為wrap_content的時(shí)候,layout_weight所代表的是你的控件要優(yōu)先盡可能的小,但這個(gè)小是有限度的,即wrap_content。

這是對(duì)于這種僅僅記住怎么用而不是為什么這么用的做法,作為一個(gè)有追求有理想的程序員是不會(huì)茍同的,因?yàn)檎f(shuō)不定哪天,咱們又忘了口訣,所以我們要從原理上理解為啥是這個(gè)樣子的。


【依照上面的理解,這個(gè)現(xiàn)象的出現(xiàn)在于layout_width="fill_parent"這個(gè)原因?qū)е碌模婚_(kāi)始下面的分析

1、系統(tǒng)先給3個(gè)TextView分配他們所要的寬度match_parent,也就指定了每一個(gè)TextView都是填滿他的父控件,這里就是整個(gè)屏幕的寬度。

2、由于如果包含layout_width這個(gè)屬性,LinearLayout將會(huì)進(jìn)行第二次measure,此時(shí)將會(huì)根據(jù)權(quán)重分配剩余的空間,在這里剩余空間=1個(gè)parent_width-3個(gè)parent_width=-2個(gè)parent_width (parent_width指的是屏幕寬度 )。

3、第一個(gè)TextView的實(shí)際所占寬度=parent_width(match_parent的寬度) + 1/5(他所占剩余空間的權(quán)重比列) * 剩余空間大小(-2 parent_width)=3/5parent_width

同理第二個(gè)TextView的實(shí)際所占寬度=parent_width + 2/5*(-2parent_width)=1/5parent_width;

第三個(gè)TextView的實(shí)際所占寬度=parent_width + 2/5*(-2parent_width)=1/5parent_width;

由此我們就可以知道為什么是按3:1:1的這個(gè)比例顯示了。】

如果我們將Layout_weight為1、2、3呢?第三個(gè)TextView直接消失了有木有!


我們可以按照上面的方法算一次就得出答案了:
1、系統(tǒng)先給3個(gè)TextView分配他們所要的寬度match_parent,也就指定了每一個(gè)TextView都是填滿他的父控件,這里就是整個(gè)屏幕的寬度。
2、由于如果包含layout_width這個(gè)屬性,LinearLayout將會(huì)進(jìn)行第二次measure,此時(shí)將會(huì)根據(jù)權(quán)重分配剩余的空間,在這里剩余空間=1個(gè)parent_width-3個(gè)parent_width=-2個(gè)parent_width (parent_width指的是屏幕寬度 )。
3、第一個(gè)TextView的實(shí)際所占寬度=parent_width(match_parent的寬度) + 1/6(他所占剩余空間的權(quán)重比列) * 剩余空間大小(-2 parent_width)=2/3parent_width
同理第二個(gè)TextView的實(shí)際所占寬度=parent_width + 2/6(-2parent_width)=1/3parent_width;
第三個(gè)TextView的實(shí)際所占寬度=parent_width + 3/6
(-2parent_width)=0parent_width;
所以三個(gè)TextView的顯示比例應(yīng)該為2:1:0,第三個(gè)TextView就消失了,因?yàn)楦鶕?jù)計(jì)算,都沒(méi)有空間可以分配給他了。
看到這里大家都清楚了解了這個(gè)計(jì)算原理,相信對(duì)于設(shè)計(jì)UI布局有所幫助,對(duì)于match_parent和wrap_content混合使用的UI布局也可以通過(guò)這個(gè)方法進(jìn)行計(jì)算設(shè)計(jì)。

接下來(lái)順帶著也給大家說(shuō)另外一個(gè)跟Layout_weight相關(guān)的屬性:weightSum
顧名思義,就是制定權(quán)重的總值,如果不指定weightSum,系統(tǒng)會(huì)將各個(gè)Layout_weight的值相加得出的總數(shù)作為權(quán)重總值,當(dāng)然我們也可以在這里顯式指定,這里也方便我們布局所用,我就在下面舉一個(gè)關(guān)于weightSum屬性的應(yīng)用:
參見(jiàn)這樣一個(gè)效果,一個(gè)總是占據(jù)一半屏幕的Button
其實(shí)XML代碼很簡(jiǎn)單:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
                    android:layout_width="match_parent" 
                    android:layout_height="match_parent" 
                    android:gravity="center" android:weightSum="2" 
                    android:orientation="horizontal"> 
    <Button 
        android:layout_width="0dp" 
        android:layout_height="wrap_content" 
        android:layout_weight="1" 
        android:text="button" />
</LinearLayout>

開(kāi)發(fā)文檔中對(duì)layout_weight屬性的有如下描述:定義weight總和的最大值。如果未指定該值,以所有子視圖的layout_weight屬性的累加值作為總和的最大值。一個(gè)典型的案例是:通過(guò)指定子視圖的layout_weight屬性為0.5,并設(shè)置LinearLayout的weightSum屬性為1.0,實(shí)現(xiàn)子視圖占據(jù)可用寬度的50。

從上面的xml中我們可以知道我們?cè)O(shè)置了weightSum為2,而對(duì)于button設(shè)置了layout_width為0且layout_weight為1(也就是weightSum的一半),我們就可以得出上面一個(gè)效果,使得Button保持占據(jù)屏幕的一半,而不用通過(guò)硬編碼去實(shí)現(xiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容