4.2 使用XML定义视图

在使用XML构建一个用户界面之前我们需要重温一下Android工程的目录结构。如图4.2所示,以HelloAndroid为例,res目录为Android工程中所使用的资源目录,用户UI所涉及的资源基本都放置在该目录下。res目录下的每一项资源文件都会由aapt(Android Asset Packaging Tool)为其生成一个对应的public static final类型的ID号,放置到gen目录下的R.java文件中,Android系统根据该ID号来访问对应资源。gen目录由ADT根据资源文件自动生成,不需要用户修改,由系统维护。res/drawable/目录用来存放工程中使用到的图片文件,drawable之后的hdpi、ldpi、mdpi分别放高分辨率、低分辨率和中分辨率的图片以适应不同分辨率的手机。Android系统会根据用户手机的配置信息自动选取合适分辨率的图片文件,无须程序员干预。res/layout/目录下存放着定义UI布局文件用的xml文件,默认文件名为main.xml;res/values/目录下存放着用于存储工程中所使用到的一些字符串信息的文件,默认文件名为strings.xml。当然,每个目录下都可以存放多个xml文件,可由开发者自行创建。由此可见,Android工程中使用的用户UI设计,以及用户UI中涉及的字符串都是由xml文件来存储的。Android系统使用xml文件来定义用户视图。

图4.2 Android工程的目录结构

单击打开values文件夹下的string.xml文件显示出如下代码:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
       <string name="hello">Hello Android!</string>
       <string name="app_name">HelloAndroid</string>
    </resources>

文件的开头部分<?xml version="1.0" encoding="utf-8"?>定义了xml的版本号和字符编码,这个部分在所有的xml文件中都会有,由系统自动添加,不需要修改。<resources>标签定义了hello和app_name两个变量,可以被HelloAndroid工程直接使用。当该文件被修改,gen目录下的R.java文件也会跟随进行更新。

双击main.xml文件,代码如下:

    <?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/textView1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello" />
    </LinearLayout>

<LinearLayout>标签定义了当前视图使用的是LinearLayout布局,也叫做线性布局方式,这种也是最常用的布局方式,Android SDK还提供其他的几种布局方式,我们会在后面的章节中进行详细的介绍。在<LinearLayout>标签中定义了该布局方式的相关属性。android:layout_width="fill_parent"和android:layout_height="fill_parent"表示该布局的宽和高充满整个手机屏幕,android:orientation="vertical"表示该布局中所放入的组件的排列方式为纵向排列。

在<LinearLayout ...>和</LinearLayout>之间就可以添加各种UI组件并设置组件的相关属性,例如组件的高度、宽度、组件的内容等,在本章第四节会详细介绍各种常见组件的使用方法。在HelloAndroid实例中添加的是一个TextView组件,相当于一个显示内容的标签。android:layout_width="fill_parent"指定其宽度覆盖满容器的宽,android:layout_height="wrap_content"指定其高度跟随其显示内容变化。android:id="@id/textView1"指明该TextView的ID值为R.java文件中id类的成员常量textView1。Android SDK提供了@[<package_ name>:]<resource_type>/<resource_name>方式以便于从xml文件中访问工程的资源。android:text="@string/hello"指明该TextView组件显示的内容为资源文件string.xml中定义的hello变量的内容。android:text属性也可以直接指定要显示的字符串,但是在实际的工程开发过程中不鼓励这种方式,而应该使用资源文件中的变量,因为这样便于工程维护和国际化。在本书中,为了节省篇幅,部分显示内容简单的组件使用了字符串直接赋值的方法。

Android工程中使用到的资源文件都会在gen目录下的R.java中生成对应项,由系统为每个资源分配一个十六进制的整型数值,唯一标明每个资源。

HelloAndroid工程中的R.java文件代码如下:

    package introduction.android.helloAndroid;



    public final class R {
        public static final class attr {
        }
        public static final class drawable {
            public static final int ic_launcher=0x7f020000;
    }
    public static final class id {
            public static final int textView1=0x7f050000;
        }
        public static final class layout {
            public static final int main=0x7f030000;
        }
        public static final class string {
            public static final int app_name=0x7f040001;
            public static final int hello=0x7f040000;
        }
    }

由该文件可见,R为静态最终类。其中public static final class layout代表的是res/layout文件夹的内容,layout类的每个整型常量代表该文件夹下的一个xml布局文件。例如,public static final int main代表的是main.xml文件,0x7f030000为系统main.xml文件生成的整型数值。在Android工程中根据该数值找到main.xml文件。public static final class string代表的是res/values/strings.xml文件,string类中的每个整型常量型成员代表strings.xml文件中定义的一个变量。例如,public static final int app_name代表strings.xml中定义的app_name变量,public static final int hello代表stings.xml文件中定义的hello变量。

在工程开发过程中,可以通过[<package_name>.]R.<resource_type>.<resource_name>方式来访问R中定义的任意资源。其中package_name为资源文件被放置的包路径,一般可以省略。resource_type为资源类型,例如layout,string,color,drawable,menu等。resource_name指的是为资源文件在类中定义的整型常量的名字。例如:

    setContentView(R.layout.main);

这行代码中,通过R.layout.main找到了布局文件main.xml,并通过setContentView方法将其设置为当前Activity的视图。要从视图中查找某个组件,需要使用findViewById方法,通过组件ID获取到组件的对象。例如要获取到main.xml中的TextView组件对象,需要执行以下代码:

    TextView textview=(TextView)findViewById(R.id.textView1);