LinearLayout是开发中使用率很高的控件,大部分开发人员感觉应该是很熟悉了,不过LinearLayout还有如下几个需要注意的地方,深刻了解以下几点可以让我们更加全面地认识LinearLayout的真正功能,避免开发中不自觉的踩坑。
一、当父控件orientation为vertical时,只有水平方向的设置才起作用,垂直方向的设置不起作用。即:left、right、center_horizontal 是生效的;top、bottom、center_vertical是无效的。
当父控件的orientation为horizontal时,只有垂直方向的设置才起作用,水平方向的设置不起作用。即:top、bottom、center_vertical是生效的;left、right、center_horizontal是无效的。
原因如下:
我们可以直接看一下LinearLayout的源码布局:
其中layoutVertical(l,t,r,b)方法中关键代码如下:
for循环是绘制子布局,switch语句是根据gravity的值确定水平方向的起始位置,三种值分别为:LEFT,CENTER_HORIZONTAL和RIGHT,由此可以看出只有水平方向的设置起作用。
二、当LinearLayout水平布局且设置gravity="bottom"的时候,其多个子控件的底部的其实是在一条水平线上的(欢迎讨论):
先看代码:
本来我以为的布局效果是这样的:
其实的布局效果是这样的:
所以能看出来,当两个子布局的底部还是需要保持在一条水平线上的,如有疑问,欢迎讨论。
三、layout_weight属性:真正意义表示“剩余”空间的占比
1、当LinearLayout的两个子控件的width都是wrap_content时,且layout_weight分别为1和2:
布局效果:
代码如下:
2、上面给人的感觉是当weight越大时所占有空间越大,其实不是这样子的,当我们将两个子控件的width都设置成math_parent时,且layout_weight依然分别为1和2时:
布局效果:
代码如下:
这表示tv1和tv2开始都占有屏幕的宽度大小,假如屏幕宽度为1080,那么"剩余"空间的占比变为1080-1080*2 = -1080.
所以tv1占有的空间为:1080 +[-1080/(1+2)]*1=720
tv2占有的空间为:1080+[-1080/(1+2)]*2=360
很明显tv1看起来比tv2占有的空间大。
所以weight值的大小跟所占有的空间大小没有必然的联系。
3、假如我们要做一个自适应的布局,左右两个按钮,可以根据屏幕的大小适应,左按钮始终最左边,右按钮始终在最右边。
效果如下:
当我们使用RelativeLayout的时候很容易实现,即分别设置设置layout_alignParentLeft="true"
与layout_alignParentRight="true"
就可以了。
但当我们使用LinearLayout如何很快就这种效果呢,这里使用到了Space属性,将此空间放置中间,并只设置其layout_weight 为1,即中间剩余空间都由该Space撑满。
代码如下:
4、weightSum属性:其与weight属性有很大关系,可通过weightSum控制weight的最大占比(假设字体占有空间宽度为120,屏幕宽度为1080)。
*当weightSum为3,子控件weight分别为1时:
效果如下:
tv1与tv2本来是一样的weight,可是结果它们都没有撑满屏幕。因为weightSum="3"
,也就是说tv1、tv2占用的宽度是 120 + 840 / 3 = 400 ,右边还有剩余280。
代码如下:
*当weightSum为3时,子控件weight分别为2时:
效果如下:
tv1与tv2本来是一样的weight且为2。此时weightSum="3"
,也就是说tv1、tv2占用的宽度是 120 + 840 * 2 / 3 = 680 ,两个都是 680,而屏幕宽度是1080,所以此时tv2被挤到屏幕之外了。
代码如下:
三、divider showDivider属性
以往我在设置分割线时,都是新增一个View,用来显示分割线,直到我发现在LinearLayout中添加分割线的新方法。LinearLayout显示分割线主要涉及divider 、showDividers 属性 : android:divider
用于设置分割线的样式,可以是xml的drawable也可以是图片。android:showDividers = "middle|end|beginning|none"
其每个选项的作用:
效果如下:
代码如下:
shape.xml布局: