在我的理解中,对开发者来说,写J2SE的程序和J2ME的程序相比,最大的区别不是他们API或者是其他一些规则、限制等的不同,更多的是两者程序界面(或者说UI)方面的区别。
我们写任何一段程序,都是需要有UI的,因为我们的程序最终是给用户去用的,即使我们写了一个工具,没有任何显式IO,我们也还是需要暴露必要的方法来提供别人使用,在此情景下,这些方法似乎也可以看作是UI。
对J2SE来说,一般都不会需要GUI,因为我们很少去写SWING、SWT程序,即使Sun力推的JavaFX,好像涉及的也不多,而对于J2ME来说,最大的困难可以就是那些GUI的实现,以及如何将程序的功能绑定到那些界面上,从界面中接收用户的输入,或者是用合适、合理的方式向界面输出,无论是通过文本,或是曲线、图形。
同理,如果你有J2EE的经验,服务后台的代码往往是相对易读、易懂、系统并且内聚的,这些代码看起来是如此的和谐、整洁、干净。而如果涉及到界面,就会陡然复杂的多,即使各种各样的framework试图要解决View与Model、Control的协作问题,结果却让大家更加的迷惑于各种配置之间。总是有GUI的程序都会看起来有些凌乱和繁芜。
似乎有些跑题… 打住…:)。咳咳,同样,对于Android开发来说,用户界面的实现应该是比较重要的和复杂的一环。好消息是,到目前为止,“神仙”们也没有发现其他更好的用户界面实现方式,所以说如果有HTML设计经验,或者说有Swing,Flash等图形设计经验,那么理解Android的UI设计,会容易的多,甚至会有似曾相识的感觉。
Android的用户界面可以有两种实现方式:使用XML或者是使用Java代码。通过直接书写代码的方式来实现界面是比较恐怖的事情。举个例子来说,如果你有DHTML的经验,那么这两者的区别可以比喻为:用XML来实现用户界面就像直接写HTML代码,而用 Java代码来实现用户界面就像用Javascript创建DOM对象来拼接页面。所以,使用XML来布局界面应该是首选。
Android使用一个XML文件来定义用户界面。为了方便理解,你可以直接把它理解为一个HTML文件。事实上,它也确实比较像一个HTML文件。
这个XML文件的格式为:
<ViewGroupClass xmlns:android="http://schemas.android.com/apk/res/android"id="@+id/string_name" (attributes)><widget or other nested ViewGroupClass>+<requestFocus/>(0 or 1 per layout file, assigned to any element)</ViewGroupClass>
这里面有一个比较重要的类叫ViewGroup,这个XML的root节点必须是一个ViewGroup,或者是一个单一的Widget(整个XML只有一个元素)。Android几乎所有的UI似乎都和ViewGroup有或多或少的关系。但是它只是一个abstract class,并不能直接使用,我们能用的,是它的一些子类,例如:
?AbsoluteLayout
?FrameLayout
?LinearLayout
?RelativeLayout
?TableLayout
?… 其他还有很多,以后用到的时候再说,一次性把这些东西都弄明白既不客观也不现实。
从上述这几个类从名字就可看的出来,他们是Layout,也就是布局,如果用过Swing的话,这些东西和Swing的那套东西一致,如果没有用过 Swing,希望你用过HTML,那么每一个Layout,可以理解为有了特定排版样式的DIV。在DIV的内部,可以放置其他的DIV,当然也可以放置最底层的元素,比如说文本、文本框、单选按钮、图片等等。这里面所说的最底层的元素,它们有一个超类叫做View,这个超类非常的超,连 ViewGroup都是它的子类。ViewGroup就是能容纳其他View的View。常用的View有很多,可以参考这里,后文再介绍。
关于XML布局,可以总结一下:
1.这个XML文件是由许多View嵌套组成的
2.如果布局中有多个元素,那么最顶层必须是ViewGroup(一个ViewGroup对象同时也是一个View对象),不可以是View,如果整个布局只有一个元素,那么最顶层元素就是这个唯一的元素。
3.在ViewGroup可以内部嵌套View(既然可以嵌套View,就更以嵌套ViewGroup了)
4.在View中,不可嵌套其他东西了,要不然它就是ViewGroup了,就是这么定义的。
用一个结构图表示:
上面提到的几个ViewGroup,稍微详细点介绍一下:
?AbsoluteLayout,绝对定位的布局方式,在它内部嵌套的元素必须指定具体的位置。
?FrameLayout,帧布局方式,说帧不太容易理解,可以说成是层布局方式,也就是说,在它内部的元素,是一层一层的叠加在一起的。如果用过Photoshop,或者Flash,这里面的层的概念是和他们一致的。如果最上层的元素是不透明的,并且比下面的元素尺寸要大,那么将看不到下面的元素,只能看到顶层元素。这些层的顺序是:最新声明的放到最前面。可以这样理解,Android按文件的书写顺序来组织这个布局,先声明的放在第一层,再声明的放到第二层,…,最后声明的放在最顶层。
?LinearLayout,线性布局方式(真不知道这该怎么翻译,其实很多技术名词还是不翻译的好),这种布局比较常用,也比较简单,就是每个元素占一行,当然也可能声明为横向排放,也就是每个元素占一列。
?RelativeLayout,相对定位的布局方式,这个比较好玩,在元素的位置的时候,使用相对位置,可以相对其他元素,也可以相对这个布局,就像我说:我现在站在pawa和 tempest的中间;或者说,我站在队伍的中间。前者就是相对其他元素来定义位置,后者是相对整个布局来定义位置。(注:pawa和tempest是Android历史上很著名的两位人物,具体请参阅 Roiding.com)。
?TableLayout,表格的布局方式,我真的不忍心翻译Table这个词,翻译成表格,似乎少了一些神韵,这里面的Table和HTML中的Table非常像,就连写法都非常像。
其实,说了这么一大堆,还是不如一个具体的实例看的痛快:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="@string/hello"/></LinearLayout>
详细解释一下:
?首先,定义了一个LinearLayout,前面中说过,这个布局要么将子元素水平排列,要么将它们竖直排列。
?android:orientation=”vertical”
声明此布局中的子元素要竖直排列,这样如果在这个布局中有两个子元素的话,那么这两个将分别各占一行,如果将这个值设置为”horizontal”,就变成了水平排列,那么两个子元素将分别各占一列,但是在这个示例中,只声明了一个子元素,你可以再为它添加一个子元素来观察效果。
?android:layout_width=”fill_parent”
声明此布局的宽度为:填满parent,这里面的parent也不好翻译,意思就是,如果它是嵌套在其他ViewGroup之中,那么那个ViewGroup的宽度就是它的宽度,如果它是顶层的元素,那么就填满屏幕。
?android:layout_height=”fill_parent”
声明此布局的高度为:填满parent。
?然后,定义了一个TextView,一个TextView,就是一块区域,用来显示文本,用这个View定义的元素只能用来显示,是不可以编辑的,如果想要可编辑的文本块,那么应该使用它的子类EditText,这个等后面遇到再说。
?android:layout_width=”fill_parent”
同上。
?android:layout_height=”wrap_content”
wrap_content的意思是:够用即可,那如果说填满整个parent都不够用呢?那就只能显示那么多了,空间不够的只能被隐藏掉了,所以必要的时候得使用ScrollView,后面再说。
?android:[email protected]/hello”
用来定义这个文本框中显示的内容,你可以直接将字符串写在这里:android:text=”hello, Roind.com”,也可以像本例中的那样,将所有的字符串放到一个资源文件中,然后在这里直接引用那个资源文件中的定义。在这里就是使用资源文件中的hello变量,在Android的缺省设置中,这个资源文件是:res/values/strings.xml。在这里你可能会问为什么声明一[email protected]/hello”就知道使用这个文件中定义的字符串呢,这个也留在后面详述,关于res目录下的东西还有很多,可以参考一下这里或者这里。
每一种元素可以定义属性有很多,并且这些属性都可以和HTML的css中的属性来类比,遇到的时候再叙或者是翻一下相关文档。