LinearLayout中layout_weight的使用
这是一个让人费解的属性.
先在网上收集一下关于weight的用法,大致的总结如下:
1.权值越小,重要度越高.
2.?
3.?
4.?
?
我凌乱了,这个到底是个什么情况!
?
还是先看google给出的官方文档:
http://developer.android.com/guide/topics/ui/layout/linear#Weight
- <?xml version="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:orientation="vertical">
- <EditText
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:hint="@string/to"/>
- <EditText
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:hint="@string/subject"/>
- <EditText
- android:layout_width="fill_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>
复制代码其效果如下:
?
大概了解到,使用weight属性可以让子组件share父容器剩余的空间.
文档边上还有一段tips:
Tocreate a linear layout in which each child uses the same amount of space on thescreen, set the?android:layout_heightofeach view to?"0dp"(fora vertical layout) or theandroid:layout_widthofeach view to?"0dp"(fora horizontal layout). Then set theandroid:layout_weightofeach view to?"1".
此方法可以让子组件平均分配父容器的空间.
于是我尝试了一下
- <?xmlversion="1.0" encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="100dp"
- android:orientation="horizontal">
- <TextView
- android:layout_width="0dp"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:background="#aa0000"
- android:gravity="center"
- android:text="1" />
- <TextView
- android:layout_width="0dp"
- android:layout_height="fill_parent"
- android:layout_weight="2"
- android:background="#00aa00"
- android:gravity="center"
- android:text="2" />
- <TextView
- android:layout_width="0dp"
- android:layout_height="fill_parent"
- android:layout_weight="3"
- android:background="#aa0000"
- android:gravity="center"
- android:text="3" />
- </LinearLayout>
- </LinearLayout>
复制代码?
不错,?大小和weight成正比!!
接着我想学以致用:
- <?xmlversion="1.0" encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="100dp"
- android:orientation="horizontal">
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:background="#aa0000"
- android:gravity="center"
- android:text="1" />
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="2"
- android:background="#00aa00"
- android:gravity="center"
- android:text="2" />
- </LinearLayout>
- </LinearLayout>
复制代码效果如下:
?
汗,怎么成
反比了(我
把0dp改成了fill_parent)
接着我尝试加个view试试,
- <?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="fill_parent"
- ? ? android:orientation="vertical" >
- ? ? <LinearLayout
- ? ?? ???android:layout_width="fill_parent"
- ? ?? ???android:layout_height="100dp"
- ? ?? ???android:orientation="horizontal">
- ? ?? ???<TextView
- ? ?? ?? ???android:layout_width="fill_parent"
- ? ?? ?? ???android:layout_height="fill_parent"
- ? ?? ?? ???android:layout_weight="1"
- ? ?? ?? ???android:background="#aa0000"
- ? ?? ?? ???android:gravity="center"
- ? ?? ?? ?? ?android:text="1"/>
- ? ?? ???<TextView
- ? ?? ?? ???android:layout_width="fill_parent"
- ? ?? ?? ???android:layout_height="fill_parent"
- ? ?? ?? ???android:layout_weight="2"
- ? ?? ?? ???android:background="#00aa00"
- ? ?? ?? ???android:gravity="center"
- ? ?? ?? ???android:text="2"/>
- ? ?? ???
- ? ?? ???<TextView
- ? ?? ?? ???android:layout_width="fill_parent"
- ? ?? ?? ???android:layout_height="fill_parent"
- ? ?? ?? ???android:layout_weight="3"
- ? ?? ?? ???android:background="#00aa00"
- ? ?? ?? ???android:gravity="center"
- ? ?? ?? ???android:text="3"/>
- ? ? </LinearLayout>
- </LinearLayout>
复制代码?
怎么还是这个效果,不理解!!
然后我试试改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="fill_parent"
- ? ? android:orientation="vertical" >
- ? ? <LinearLayout
- ? ?? ???android:layout_width="fill_parent"
- ? ?? ???android:layout_height="100dp"
- ? ?? ???android:orientation="horizontal">
- ? ?? ???<TextView
- ? ?? ?? ???android:layout_width="fill_parent"
- ? ?? ?? ???android:layout_height="fill_parent"
- ? ?? ?? ???android:layout_weight="2"
- ? ?? ?? ???android:background="#aa0000"
- ? ?? ?? ???android:gravity="center"
- ? ?? ?? ???android:text="2"/>
- ? ?? ???<TextView
- ? ?? ?? ???android:layout_width="fill_parent"
- ? ?? ?? ???android:layout_height="fill_parent"
- ? ?? ?? ???android:layout_weight="3"
- ? ?? ?? ???android:background="#00aa00"
- ? ?? ?? ???android:gravity="center"
- ? ?? ?? ???android:text="3"/>
- ? ?? ???
- ? ?? ???<TextView
- ? ?? ?? ???android:layout_width="fill_parent"
- ? ?? ?? ???android:layout_height="fill_parent"
- ? ?? ?? ???android:layout_weight="4"
- ? ?? ?? ???android:background="#00aa00"
- ? ?? ?? ???android:gravity="center"
- ? ?? ?? ???android:text="4"/>
- ? ? </LinearLayout>
- </LinearLayout>
复制代码囧!
Google的android大神们,我凌乱了!
Android屌丝程序员毅然决定去看源码:
从ViewGroup的measure方法开始,接着到LinearLayout的measureVertical方法(假设linear是垂直分布的,水平类似),有以下代码片段:
翻译: 如果linear的尺寸Mode为EXACTLY, 并且该子组件的height为0,weight>0,则这次不计算组件的高度,下面再计算.
接着往下看:
?
翻译:
delta为子组件第一次计算完后,linear还剩余多少高度。
Share为第二次子组件能够分配到的剩余空间。
这个样看来,由于把子组件的属性改为fill_parent(height值为-1)之后,子组件的高度被计算了两次.
若有2个组件, 权值分别为1 , 2, 设宽度为X,则计算如下:
Delta =x - 2x(第一次计算) = -x(囧,这个值居然是负的);
X1 = x+ share1 = x + (delta * 1 / 3) = 2/3x(第一次计算的值和剩余的相加)
X2 = x+ share2 = x + (delta * 2 / 3) = 1/3x
效果恰好是成反比!!(网上很多人都误以为真成反比了!)
若有3个组件,权值分别为 1,2,3 设宽度为X,则计算如下:
Delta = x - 3x = -2x;
X1 = x + share1 = x + (-1/6 * 2x) = 2/3x
X2 = 1/3x
X3(上面两个用完空间了!)
所以效果还是:
?
接着算?权值为?2,3,4的结果如下:
Delta = -2x
X1 = x - 4/9x = 5/9x
........
效果就如下了:
总结:
1.要想让weight和你预想的效果一致,子组件的高度或者宽度需要设置为0dp,父容器(LinearLayout)要设置为fill_parent或者确定的值且不能为wrap_content,即mode 为 EXACTLY.
?
2.谨慎在 LinearLayout中使用 layout_weight(除非你使用正确), 这样所有子组件的尺寸会被计算两次,将影响性能.
?
3.Google的大神们为了赶版本,这个属性的逻辑有点混乱,文档不够详细,给俺们Android屌丝程序员们埋了好多坑!
?
4.关于网上的结论,什么权值大小和重要度成反比,子组件用wrap_content权值才会成正比等,都是错误的!