先看下图,我要用LinearLayout实现如下效果,2要自适应大小,也就是wrap_content,1要占满剩下的空间怎么办?(当然用相对布局很简单)
如果我要再实现一个更变态点的需求呢,就是2位置要动态变换呢(右图所示效果),根据不同的状态,设置2位置不同控件的隐藏和显示,这种情况下,用RelativeLayout实现就有点麻烦了,你要找到一个基准控件,然后根据他来布局其他控制,如果有一个设置不对,显示的布局就没有这个效果
先分析此问题的难点:
(1)控件2的宽度不确实的,导致1不知道自己的宽度要设为多少。
(2)控件2的位置有多个控件,需要动态控制不同控件来显示和隐藏
如果用LinearLayout就简单很多,linearlayout有一个属性,就是本篇的主角android:layout_weight属性,它是属于LinearLayout特有的。
用LinearyLayout实现有两种写法,都差不多。写提供代码
实现一
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/hello" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name" />
</LinearLayout>
实现二
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/hello" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name" />
</LinearLayout>
其实这两种实现只有一点区别,就是第一个button的layout_weidth,一个是fill_parent,另一个是0dip。其实两种都差不多,下边详细讲解:
首先大家要明白一个概念,就是一个控件(View)本身是可以无限大的,也说是说在它自己的onDraw()函数中,你想要它多大,它就可以有多大,但是为什么我们只能看到一部分呢?
这就要"归功"于android:layout_width和height属性,很多人认为这个是设置控制本身大小的,其实这个理解有偏差,layout_width这个属性不是控制一个子控件它本身的大小(自身大小由它
自己决定),而是父布局提供给这个控件的显示窗口大小,这里叫申请大小(下面同理)。
然后来讲解详细的计算过程,当LinearLayout包含的视图weight>0时,它会mesure两次(这里以上面第一个布局来讲解)
第一次,计算剩余空间,就是用屏幕的宽度减去子控件申请的宽度。设屏幕宽度为TW,第一个button的申请宽度设为x1,weight为w1,第二个button的申请宽度设为x2,weight为w2,剩余空间设为delta
表达示为 delta = TW - (x1+x2)
第二次,分配空间,即父视图最终提供给子控件的显示窗口的大小,
button1的最终显示大小为 x1+delta*w1/(w1+w2),
button2的最终显示大小为 x2+delta*w2/(w1+w2),
结合上面的实例来说明
上面第一个布局,假设手机分辨率为480x320,btn1申请宽度为fill_parent=320,btn2的申请宽度为wrap_content,这个是会调用控件自身的onMeasure计算出来的,假设计算结果为40,那么
第一步剩余空间就是320-(320+40) = -40,
第二步,分配空间,btn1的最终显示空间为320+(-40)*(1/(1+0)) = 280,btn2的最终显示空间为40+(-40*0/(1+0)) = 40
这样就满足了我们开始的那个需求,
再分析第一个布局,其实本质和第一个布局一样,只是把减去变为加上而已
第一步,剩余空间 = 320-(0+40) = 280;
第二步,分配 btn1最终空间 0+280*1/(1+0) = 280,btn2的最终空间为40+280*0/(0+1)