Android界面布局基本知识
Android手机操作系统在模拟器中进行相关的编写,可以帮助我们实现各种功能需求。尤其是在界面的操作方面显得更为突出。在这里我们就可以对Android界面布局的相关操作来对这方面的知识进行一个深入的了解。
原先一直做iphone的开发,现在因为工作需要再加上兴趣,转作Android的开发了,特在这记录学习Android的心得,以便以后需要时有个地方可以查找。
做应用程序,界面是基本的,所以我先研究了Androidi的界面的制作,原以为很简单了,和其他iphone,vc一样,做界面是所见即所得的模式,后来一看,才发现不是这样的……
andorid的界面,需要写在res/layout的xml里面,一般情况下一个xml对应一个界面。
做Android界面布局有点像写html(连注释代码的方式都一样),要先给Android定框架,然后再在框架里面放控件,Android提供了几种框架,AbsoluteLayout,LinearLayout,RelativeLayout,TableLayout,FrameLayout
FrameLayout:里面只可以有一个控件,并且不能设计这个控件的位置,控件会放到左上角
LinearLayout:里面可以放多个控件,但是一行只能放一个控件
TableLayout:这个要和TableRow配合使用,很像html里面的table
AbsoluteLayout:里面可以放多个控件,并且可以自己定义控件的x,y的位置
RelativeLayout:里面可以放多个控件,不过控件的位置都是相对位置
(Android界面布局好像还可以直接引用一些view,如ScrollView等)
框架的xml如下:
Android:id="@+id/widget36" Android:layout_width="fill_parent" Android:layout_height="fill_parent" >
上面代码中以Android:开头,表示控件的属性,fill_parent是系统自带参数,表示的宽或高,还有一个wrap_content,表示刚好合适的宽或高。除了上面的三个属性外,一些其他的属性,Android:background="#FF0000FF",设置框架的背景色,Androidrientation="vertical"用来设置这个框架里面的走向属性。
UI界面,对于每个应用而言,是它与用户进行交互的门脸。好的门脸,不只是是要亮丽可人,还能秀色可餐过目不忘,甚至还应该有涵养有气质,彬彬有理温柔耐心。
Android的UI框架,的,是资源和Layout体系,然后,通过完善的控件库,简明的接口设计,进一步帮助开发者,能够快的搭建自己需要界面。
UI控件
做UI,有时候就像搭积木,在Android中,这个原子的积木块,就是View.所有其他的UI元素,都是派生于此类的子孙类们。
又从SDK中偷来张图,用来描述Android的UI控件结构,在每一个window下,这都是一个标准而完整的树结构。View有一个子类ViewGroup,它相当于一个容器类或者是复合控件,所有派生与ViewGroup的子类在这颗UI树中都可以承担着父节点的职责,而另一些绕过ViewGroup从View直通下来的,就只能蜷局在叶节点的范畴内了。
之所有说这是一个很标准的控件树,是因为父控件对子控件有的掌控权,每个子控件的占地面积和位置,都是基于父控件来分配的,它能够接受和处理的事件,也是父控件派发下去的。这样的结构,被很多平台和框架广泛的认可,和传统的win开发和杯具的Symbian相比,虽然因为事件传播途径变长了,很多操作的效率变低了,但整个结构更有层次性,每个控件只需要多其父控件负责指挥子控件就好,职责明确,逻辑简单,利于开发和设计。
谈及任何平台的控件,都有一些不可避免的主题,比如,每个控件如何标识,如何设定大小和位置,如何接受和处理事件,如何绘制,诸如此类。
标识
在Android中,你可以为每个控件选择设定一个id,这个id的全局的性不需要保证,但在某个局部的范围内具有可识别性,这样就可以通过这个id找到这个控件。在父控件中逐级的find比较,找到id匹配的控件,然后再做转型,是一个比较重量的操作,于是Android又为控件憋出另一个属性,tag.它接受任意object类型的数据,你可以把和这个控件对象相关的内容堆在里面。比如,在list中,我们常常将和每个list item相关的所有控件元素封装成一个object,扔到tag中,就不需要每次都去比较id进行寻找,更加高效快捷。
尺寸
在Android中,控件重要的大小属性,就是width/height,开发者可以明确的指明控件的大小,可以设定成为fill_parent和wrap_content,这样的概念性的大小。丈量并设定控件的位置,是通过两步来进行的。
步是measure.它传入此控件的width/height信息,控件会根据自己的参数,计算出真实需要的width/height,然后调用setMeasuredDimension方法,缓存成成员变量,留作后用。
在计算出大小之后,会进行另一个步骤,layout.在这个过程中,父控件会计算其上各个子控件的位置,从而完成整个大小和位置的确定流程。整个measure和layout的流程,都是自上到下,从树顶往叶子来推进的。
当开发人员需要自定义控件的时候,可能需要关注这些内容,通过重载onMeasure和onLayout方法,可以定义自己控件的丈量方式。
事件
在Android中,所有的按键,触屏等事件,都是从顶至下进行分发的。每个ViewGroup的对象,会维系一个focused变量,它表示在这个父控件中具备focus的控件,当有按键时间发生的时候,会找到这个focused子控件,并传递给它。同理,触屏事件的分发也是类似,只不过和focus无关,父控件会遍历所有子控件,看看谁处于触碰位置,从而传递给谁。
Android的事件处理逻辑,采用的是观察者模式。Android的控件提供了一些列的add/set Listener的接口,使得外部观察者,有机会处理控件事件。比如,你需要在某个button被点击时做一些事情,你就需要派生一个View.OnClickListener对象作为观察者,调用该控件的setOnClickListener接口注册进去,当button被点击,就可以获得处理点击事件的机会了。当然,有的时候,你需要处理的逻辑更为复杂,光是站在外面围观叫好不能解决问题,可能就需要派生某个控件,去重载onXXXX之类的事件处理函数,进行更完整的控制。
焦点
对于一个非触屏的机器,焦点的维系是一个极其重要的事情,而在有触屏的年代,焦点的地位虽有所下降,但依然还是需要妥善保护的。
Android中,是以控件树为单位,来管理焦点的。每个控件,可以设置上下左右四向的focus转移对象。当在一个控件上发生焦点转移事件,Android会如前述,自顶向下根据设定好的焦点转移逻辑,跳转到正确的控件上。和Symbian相比,真是,真是…
Layout
Layout是一类特殊的ViewGroup控件,它们本身没有任何可显示内容,形如透明的玻璃盒子,存活的理由,就是其中的内部结构,能够更好的摆放它的子控件们。
比如线性的Layout,LinearLayout.放入这个Layout的子控件,会按水平或垂直方向,排排坐,一个挨着一个按顺序排列下去。TableLayout,可以将子控件按照表格的形式,一枚枚放置好。而RelativeLayout则更灵活,可以设定各个控件之间的对齐和排列关系,适合定制复杂的界面。
有了Layout的存在,控件和控件之间不再割裂的存在,而是更有机的结合在了一起,设定起来也更为方便。比Symbian那样人肉维系各个控件的关系,轻松自在多了。
更多这些问题的完整答案,参见SDK中View的页面:/reference/android/view/View.html.
实现
有了这些对Android的UI控件的认知,可以看更整体性的实现细节,那就是Activity的UI实现。
如上图所示,假设你做了个如同虚线框中结构的一个界面,通过Activity的setContentView方法,塞进了Activity中,就会形成图示的一个逻辑关系。每一个Activity,都包含一个Window对象,它表示的是一个的一整屏幕上面的界面逻辑。在Android源码中,其实现是MidWindow,它包含了一个FrameLayout对象,呈现出来就是那种带着一个title的界面样子。自定义的一堆控件,会插进Window的界面部分,在Activity中,所有事件的处理逻辑,是Window先享用,没消费掉在交由这堆控件吃剩的。
在整个控件树的顶端,是一个逻辑的树顶,ViewParent,在源码中的实现是ViewRoot.它是整个控件树和WindowManager之间的事件信息的翻译者。WindowManager是Android中一个重要的服务。它将用户的操作,翻译成为指令,发送给呈现在界面上的各个Window.Activity,会将的控件注册到WindowManager中,当用户真是触碰屏幕或键盘的时候,WindowManager就会通知到,而当控件有一些请求产生,也会经由ViewParent送回到WindowManager中。从而完成整个通信流程。
当你接触过一段时间的android应用开发,了解到了一些android的知识后,你应该能够在心中形成这样的印象:android的开发分为两块。一个是资源部分,一个是资源操作部分:详细点说的话,就是一个是对资源的导入、设置、整合等这些方面的工作,另一个就是对资源的调用、使用、控制(甚至改变)等这些方面的工作。前者在一个典型的android工程中的表现形式就是assets文件夹中的音频、视频等原生资源文件和res文件夹中的各式各样的xml文档文件以及形形色色的图片文件--很容易想到的是,这些东西是无法程序在运行时改变的,也就是静态的。后者在android工程则表现为src文件夹和gen文件夹中各式各样的java文件(有的是你手动输入生成的,有的则是adt通过aidl自动生成的),而通过开发人员的设计以及实现,这部分在应用运行时是可能发生改变的,也就是动态的。NZR平坦软件园
而界面的开发便处在了这样一个极为重要的位置之上:沟通资源和对资源的操作(后者我们还可以简述为软件的"功能")这两个部分。也就是说,如果你想要做出一个标准为"差强人意"的android界面的话,你至少首先对android的两大开发部分有一个大致上的了解--你得会写xml代码,以至于你可以形成一个又一个的还算符合逻辑的界面结构;你得学会P图(或者让会P图的人懂得该给你P什么图),抑或搜图,从而可以为你的界面准备一些养眼的图片资源,以给人眼前一亮的感觉;你得掌握android.widget包里面的一些常用类的使用方法以及一些使用技巧,从而可以让你的资源在应用运行时可以以很舒服的形态展示出来;你甚至得对android的窗口运行、管理机制有一定的了解,以到达更自由地定制界面特性的目的。
免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。