Android的应用编写基本都会有一个界面,而Android应用的编写逻辑是遵循MVC模式的,它将界面和控制逻辑是分开的,这样一来,界面编写就和应用的业务逻辑是分开的,更改系统业务逻辑也无需改变前台界面,增强了应用的可维护性,降低长期开发成本。
在Android系统中,应用程序的界面是通过一系列的布局文件实现的。这些布局文件使用XML语法编写,使用标签中的属性指定界面上的视图控件本身的属性和控件之间的关系属性。
Android系统提供了几个非常灵活的布局,但是日常开发中我们最常使用的也就是其中的几种。本文我们重点介绍在Android应用开发中使用频率很高的四种布局:线性布局,相对布局,帧布局,百分比布局。所谓这些布局,其实就是定义了它内部的视图控件的位置怎么排放,约束关系等等。我们可以布局看成是一个盒子,然后我们的button,edittext等控件就是需要放到这些盒子中的物件,同时布局的内部也可以存放其他的布局,也就是说,大盒子的内部可以是小的物件,也可以是小的盒子。
需要强调两点,第一点,在Android应用开发中,布局XML文件不是必须存在的,我们完全可以在java代码中使用代码来构建我们的布局,但是这样的话我们的代码会变得丑陋无比,后期无法维护。这并不是说在代码中控制界面不可取,正确的做法是大部分的布局我们使用xml文件构建,只是在某些特殊的情况我们需要使用代码来控制添加或者删除某些界面上的控件。第二点就是,Android官方提供的android studio工具中的视图化的界面编辑非常方便,但是大家千万不要直接使用这个工具编辑界面,因为在这个界面上妥妥拽拽不能做到精细化设计界面,我们还是需要手动编辑文本,然后使用这个工具进行效果预览就可以了。
线性布局LinearLayout
顾名思义,线性布局的意思就是它内部的控件的位置排列是线性的,要么垂直,要么水平。我们先看一个例子:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.createchance.uilayouttest.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 3"/>
</LinearLayout>
这个布局的效果如下图:
这里,我们看到默认的控件位置是水平排放的。我们可以使用android:orientation属性来指定这个线性的水平布局,可以选择的参数是:horizontal(水平,默认值)和vertical(垂直),当我们在LinearLayout标签下增加了android:orientation=”vertical”之后布局就成了下面这样:
按照标准来说,每一个控件都应该使用android:layout_width和android:layout_height字段来描述这个控件的宽和高信息,如果没有的话编译会报错(后面我们会看到在百分比布局中,控件可以没有这两个属性)。在线性布局中需要注意的一点就是,如果排列方向是horizontal的话,那么内部的控件的宽度就不能指定为match_parent(铺满父窗口),因为如果指定的话就会是下面这个效果:
你会奇怪,怎么第二个和第三个button不见了?是的,他们被button 1挤出去了,你看不见他们了。因为你的button 1的宽度是match_parent,因此它霸占了整个宽度,第二个和第三个button没有地方待了!同理,如果你的布局方向是vertical的话,那么内部的控件的高度就不能是match_parent。
在线性布局中,我们需要注意的一个属性就是android:layout_gravity,这个属性和android:gravity属性看起来有些类似,但是他们之间是有很大的区别的。android:layout_gravity用于制定控件在布局中的对齐方式,而android:gravity用于执行文字或者内容在控件本身中的对齐位置。android:layout_gravity和android:gravity可选值是类似的,但是需要注意的是,当布局的方向是horizontal的时候,只有垂直方向的对齐才是有效的,因为这个时候水平方向的长度是不确定的,如果你新添加一个控件的话水平长度就发生变化了。同理,如果你的布局方向是垂直的,那么只有水平方向的对齐才有效。我们将刚才界面上的三个按钮错开排放:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.createchance.uilayouttest.MainActivity">
<Button
android:layout_width="wrap_con