一般的,一个Android视图中会有很多的控件。为了界面的合理、美观,我们需要让它们按照我们设计好的思路排列在界面上,那么,我们就需要容器来存放这些控件,并控制它们的位置排列,就像HTML中的div、table一样,Android布局也起到了同样的作用。
Android布局有很多种,它们各有各的特点,分别应用在不同的场合,而且可以嵌套使用。我们要根据我们的界面设计选择合适的布局,可能有些时候不同的布局可以达到同样的效果,但是“层次”越少的布局执行效率越高,因此,我们要选择最合适的布局来尽量减少界面的“层次”。下面,我们一个个来看看这些布局。
LinearLayout,也就是线性布局,是Android开发中最常用的布局之一。它以你为它设置的水平或垂直的属性值,来排列所有的子元素。包含在LinearLayout里面的控件按顺序排列成一行或者一列,类似于Swing里的FlowLayout和Silverlight里的StackPanel,所有的子元素都被堆放在其它元素之后。因此一个垂直列表的每一行只会有一个元素,而不管他们有多宽。而一个水平列表将会只有一个行高(高度为最高子元素的高度加上边框高度)。LinearLayout保持子元素之间的间隔以及互相对齐(相对一个元素的右对齐、中间对齐或者左对齐)。
android:orientation="vertical"//垂直布局 android:orientation="horizontal"//水平布局 |
如果是垂直排列,那么将是一个N行单列的结构,每一行只会有一个元素,而不论这个元素的宽度为多少;如果是水平排列,那么将是一个单行N列的结构。如果搭建两行两列的结构,通常的方式是先垂直排列两个元素,每一个元素里再包含一个LinearLayout进行水平排列。
下面,我们以一个简单的例子来加以说明。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="textview1"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="textview2"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="textview3"/> </LinearLayout> |
效果如图3-2所示。
图3-2 LinearLayout垂直布局
接着我们将android:orientation="vertical"属性改为"horizontal"来看看效果,如图3-3所示。
图3-3 LinearLayout水平布局
可以很明显的看到,我们将布局模式由“垂直布局”改为“水平布局”之后,控件由按行排列变成了按列来排列。
另外,LinearLayout还支持为单独的子元素指定weight。好处就是允许子元素可以填充屏幕上的剩余空间。这也避免了在一个大屏幕中,一串小对象挤成一堆的情况,而是允许他们放大填充空白。子元素指定一个weight值,剩余的空间就会按这些子元素指定的weight比例分配给这些子元素。默认的weight值为0。还是用上面“水平布局”的例子,我们给第一个文本框添加上android:layout_weight="1"属性,效果如图3-4所示。
图3-4 LinearLayout中layout_weight的作用
可以看到,textview1将textview2和textview3文本框之外的空白都填充了。
经验分享: 在LinearLayout线性布局中,我们有的时候需要设置为水平居中/垂直居中,但是偶尔莫名其妙的设置对了但是却并不起效果,这个时候你就需要注意了,看它是垂直线性布局还是水平线性布局。 当垂直线性布局时,则水平居中有效;当水平线性布局时,则垂直居中有效。 如果这些都没有问题,则看看是不是高度或宽度设置有问题。 如果此时为垂直线性布局,你想设置为水平居中, android:width的属性设置为fill_parent则没有效果,设置为wrap_content则有效,另外,通过设置android:gravity="center_horizontal"也可以实现这样的效果,但需要注意的是,此时的android:width的属性需设置为fill_parent。垂直居中亦然。 |
RelativeLayout,即相对布局是一种比较灵活的布局。首先RelativeLayout是一个容器,它里边的元素的位置是按照相对位置来计算的。RelativeLayout允许子元素指定他们相对于其它元素或父元素的位置(通过ID指定)。因此,你可以以右对齐、以左对齐,或上下,或置于屏幕中央的形式来排列两个元素。元素按顺序排列,因此如果第一个元素在屏幕的中央,那么相对于这个元素的其它元素将以屏幕中央的相对位置来排列。可能这样说还不是很好理解,我们也以一个例子来加以说明。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/name_text" android:layout_centerHorizontal="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户名"/> <EditText android:id="@+id/name_edit" android:layout_width="120dp" android:layout_height="wrap_content" android:layout_alignTop="@id/name_text" android:layout_toRightOf="@id/name_text"/> <TextView android:id="@+id/pwd_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密码" android:layout_below="@id/name_text" android:layout_alignLeft="@id/name_text" android:layout_marginTop="50dp"/> <EditText android:id="@+id/pwd_edit" android:layout_width="120dp" android:layout_height="wrap_content" android:password="true" android:layout_alignTop="@id/pwd_text" android:layout_alignLeft="@id/name_edit"/> </RelativeLayout> |
在上面的布局文件中,我们让第一个元素name_text相对于父元素“水平居中”:android:layout_centerHorizontal="true";
接着让name_edit位于name_text的右边:android:layout_toRightOf="@id/name_text";
并与name_text的顶部对齐:android:layout_alignTop="@id/name_text";
然后让pwd_text位于name_text的下方:android:layout_below="@id/name_text";
为了更好的看到效果,我们再让它向下位移50dp:android:layout_marginTop="50dp";
并让它与name_text左对齐:android:layout_alignLeft="@id/name_text";
最后是pwd_edit,我们让它与pwd_text的顶部对齐:android:layout_alignTop="@id/pwd_text";
并与name_edit左对齐:android:layout_alignLeft="@id/name_edit"。
下面来看看具体的效果图,如图3-5所示。
图3-5RelativeLayout相对布局
经验分享: 出于性能上的考虑,对于相对布局的精确位置的计算只会执行一次。也就是说,如果使用XML来指定这个layout,在你定义它之前,被关联的元素必须定义。而且如果在这个RelativeLayout中有元素a和元素b,要定义元素a在元素b的右边,元素b则需要先被定义。 |
另外,RelativeLayout中有很多不同于其他布局的属性,也正是由于这些属性使得RelativeLayout具有很强的灵活性,我们应该熟练地掌握它们。
表3-1详细说明了相对于给定ID的控件的一些属性。
属性 |
说明 |
android:layout_above |
将该控件的底部置于给定ID的控件之上 |
android:layout_below |
将该控件的底部置于给定ID的控件之下 |
android:layout_toLeftOf |
将该控件的右边缘与给定ID的控件左边缘对齐 |
android:layout_toRightOf |
将该控件的左边缘与给定ID的控件右边缘对齐 |
android:layout_alignBaseline |
将该控件的baseline与给定ID的baseline对齐 |
android:layout_alignTop |
将该控件的顶部边缘与给定ID的顶部边缘对齐 |
android:layout_alignBottom |
将该控件的底部边缘与给定ID的底部边缘对齐 |
android:layout_alignLeft |
将该控件的左边缘与给定ID的左边缘对齐 |
android:layout_alignRight |
将该控件的右边缘与给定ID的右边缘对齐 |
表3-1 相对于给定ID的控件的属性
表3-2详细说明了相对于父组件的一些属性。
属性 |
说明 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
android:layout_marginTop |
上偏移的值 |
android:layout_marginBottom |
下偏移的值 |
android:layout_marginLeft |
左偏移的值 |
android:layout_marginRight |
右偏移的值 |
表3-2 相对于父组件的属性