wrap_content 使视图自动调节尺寸到内容所需的大小布局(layout)是一个活动的用户界面的结构。它定义了布局结构并包含了所有将向用户呈现的元素。可以通过两种途径声明布局:
- 在XML中声明UI元素。Android提供了一组直观的XML词汇,它与View类及其子类(比如部件和布局所要使用的)对应。
- 在运行时实例化布局元素。程序可以通过代码创建View和ViewGroup对象(并设置其属性)。
Android框架可灵活地使用以上一种或两种方法来声明并管理程序界面。比如,可以在XML中声明程序的默认布局,像是屏幕上显示的元素及其属性。之后可以在程序中添加代码以在运行时修改包括XML中所声明的屏幕物件的状态。
- Eclipse的ADT插件提供了XML的布局预览——打开XML文件后选择Layout标签。
- 还可以试着用层次查看器工具(Hierarchy View Tool)来调试布局——它显示了布局的属性值,以间距/边缘指示器来画出框架,并在通过模拟器或实机调试时渲染整个视图。
- layoutopt工具可以快速分析布局和层次中的效率低下或其他问题。
在XML中声明UI的优势在于可以更好地分离程序显示与控制行为的代码。UI描述不属于程序代码。意味着不必修改源代码并重编译就能修改UI。比如,可以为不同屏幕方向、不同屏幕尺寸与不同语言创建多个XML布局。另外,在XML中声明布局使UI的可视化变得更为容易,也就更容易调试。因此,本文档着眼于讲授如何通过XML声明布局。如果对于在运行时实例化View对象的话,可以参考ViewGroup和View类的内容。
通常,用以声明UI元素的XML词汇和结构、类与方法的命名紧密相关,元素名称对英语类名,属性名称对应于方法。事实上,这一对应关系非常直接以至于可以猜出XML属性对应的类方法,或猜出一个给定的XML元素对应于哪一个类。不过,注意并非所有词汇都是相同的。在一些情况下,命名上有些小差异。比如,EditText元素有一个text属性,它对应的是EditText.setText()。
Tip:可以在”常用Layout对象“一文中了解更多不同的布局类型。在”Hello Views“教程中有关于如何构建不同布局的一系列教程。
编写XML
使用Android的XML词汇,可以像用HTML创建网页一样通过一系列的嵌套元素快速地设计UI布局与其中包含的屏幕元素。
每一个布局文件必须包含一个View或ViewGroup对象作为根元素。一旦定义了根元素,就可以添加其他的布局对象或是部件作为其子元素,逐渐构造出能够用于定义布局的视图层次。比如,下面是一个XML布局,它使用了垂直LinearLayout并含有一个TextView和一个Button:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?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="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout> |
在XML中声明了布局之后,以.xml后缀保存该文件与Android项目的res/layout/文件夹,这样它就能被正确编译。
为了方便,UI相关的类的API参考文档列出了与类的方法对应的可用的XML属性,以及继承属性。
要了解更多关于可用的XML元素和属性以及XML文件的格式的信息,参阅“布局资源”。
稍后将讨论这里出现的每一个属性。
载入XML资源
在编译程序时,每一个XML布局文件会被编译为一个View资源。需要在该活动的onCreate()方法中使用程序代码来载入布局资源。通过调用setContentView(),以R.layout.layout_file_name的形式传递这个引用给布局资源。比如,如果XML布局被保存为main_layout.xml,那么应该像这样将它读入活动:
1 2 3 4 |
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView.(R.layout.main_layout); } |
活动中的onCreate()回馈方法在活动被启动时被Android框架调用(参见“应用程序基础”中的关于生命周期的讨论以了解更多)。
属性
每一个View和ViewGroup对象支持其自有的XML属性。有些属性专用于某一View对象(比如,TextView支持textSize属性),但这种属性也会被扩展于这个类的View对象所继承。一些属性对所有View对象都适用,因为它们继承于根View类(比如id属性)。同时,其他的属性被看作是“布局参数”,在View对象的ViewGroup父对象中定义用以描述View对象特定的布局位置。
ID
任何View对象都有一个整数ID与之关联,以在层次树种唯一确定该View。当程序在编译时,ID作为整数被引用,不过ID却是作为字符串被分配给布局XML文件的。这是一个对所有View都适用的XML属性(由View类定义),将被经常使用。ID在XML标签中的语法格式如下:
1 |
android:id="@+id/my_button" |
字符串头部的@符号表明XML语法分析器应该把ID字符串的剩余部分识别为ID资源并分析与扩展它。加号(+)意味着这是一个新的资源名,必须被创建并添加至资源中(在R.java文件里)。还有其他许多Android框架提供的ID资源。在引用Android资源ID时,不需要使用加号,但必须像这样加上android包的命名空间:
1 |
android:id="@android:id/empty" |
由于有了android包的命名空间,现在可以引用android.R资源类中的ID,而不仅仅是本地资源类。
为了在程序中创建视图并引用它,通常采用这样的方式:
1、在布局文件中定义一个视图/部件,之后分配其一个专有的ID:
1 2 3 4 |
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/> |
2、然后创建该视图对象的一个实例,并从布局中获取它(通常是在onCreate()方法中):
1 |
Button myButton = (Button) findViewById(R.id.my_button); |
当创建一个RelativeLayout时为视图对象定义ID是很重要的。在相对布局(relative layout)中,同层次视图可以通过引用其唯一的ID来相对地定义它们之间的布局。
在整棵层次树中ID不需要是唯一的,但在被搜索的这部分中它需要是唯一的(不过由于通常会搜索整棵树,所以最好尽可能设定唯一的ID)。
布局参数
被命名为layout_XXXX的XML布局属性为View定义了其布局参数以适合于其所在的ViewGroup。
每一个ViewGroup类有一个扩展于ViewGroup.LayoutParams的嵌套类。这个子类包含了定义每一个子视图适合于视图组的尺寸和位置的正确类型。如下图所示,父视图组为每一个子视图(包括子视图组)定义了布局参数。
注意每一个LayoutParams子类都有其自有的赋值语法。每一个子元素必须定义适合于其父元素的LayoutParams,不过可以为它的子元素定义不同的参数。
所有的视图组包含有宽度和高度参数(layout_width 和 layout_height),每一个试图都需要定义它们两者。许多LayoutParams还包含可选的边距等参数。
可以通过精确的单位来制定宽度和高度,不过往往不这样做。更常见的做法是用一下常量之一来设置宽度或高度:
- wrap_content 使视图自动调节尺寸到内容所需的大小
- fill_parent (在API Level 8中重命名为match_parent)使视图变为其父视图所允许的最大尺寸
通常,不推荐用绝对单位比如像素来定义布局的宽度和高度。改用相对度量方式比如密度无关像素单位(dp),wrap_content,或fill_parent是更好的方式,因为这样可以帮助确保程序可以在不同屏幕尺寸的设备上正确显示。可用的度量方式在“可用资源”文档中被定义。
布局位置
一个视图占有一块矩形区域。视图有一个通过一对左侧和顶部坐标表示的位置,以及通过宽度和高度表示的两个维度。位置和维度的单位是像素。
可以通过调用getLeft()和getTop()方法来获得一个视图的位置。前者将返回视图所占矩形区域的左侧或者说X坐标,后者返回该矩形的顶部或者说Y坐标。这两种方法返回的位置都与其父视图相关。比如,如果getLeft()返回20,就意味着该视图处于其直接父视图左侧边缘起向右20像素的位置。
另外,有一些便利的方法可以用来避免不必要的计算,即getRight() 和getBottom()。这些方法返回视图矩形区域的右侧和底部坐标。比如,调用getRight()就类似于进行了getLeft() + getWidth()的计算。
尺寸、间隙和边距
视图的尺寸由宽度和高度表示。一个视图实际上有两组宽度和高度的数值。
第一组是测量宽度(measured width)和测量高度(measured height)。它们订立了一个视图在其父视图内的大小。可以通过调用getMeasuredWidth()和getMeasuredHeight()来获取它们的值。
第二组是宽度和高度,有时候也被称为绘制宽度和绘制高度。这两个维度是视图在绘制和布局后在屏幕上的实际尺寸。它们的值有可能和测量宽度和高度不同。宽度和高度可以通过调用getWidth()和getHeight()获得。
为了测量一个视图的尺寸,需要考虑它的间隙(padding)。可以用像素表示视图上下左右的间隙。可以用一定像素的间隙来代替视图的内容。比如说,值为2的左侧间隙可以将视图的内容自左侧边缘向右推2个像素。可以用setPadding(int, int, int, int)方法来设定间隙,而通过getPaddingLeft()、getPaddingTop()、getPaddingRight()和getPaddingBottom()方法可以获得间隙的值。
尽管一个视图可以定义间隙,不过它不支持任何类型的边距(margin)。但视图组支持边距。参考ViewGroup和ViewGroup.MarginLayoutParams以获得进一步的信息。
关于维度的更多信息,请参见“维度的值”。
本页部分内容根据Android Open Source Project创作并共享的内容修改,并在知识共享 署名2.5许可协议中所述条款的限制下使用。