深入Android 【六】 —— 界面构造

简介:

界面构造

UI界面,对于每个应用而言,是它与用户进行交互的门脸。好的门脸,不只是是要亮丽可人,最好还能秀色可餐过目不忘,甚至还应该有涵养有气质,彬彬有理温柔耐心。
对于开发者来说,锻造这样的面容,不但需要高超的技艺,也需要有称手的工具和对得起党的料子。俗话说,朽木不可雕也,芙蓉不是一日炼成的,不是什么平台都能叫特能书。有套好用的UI框架,对于开发者而言,真有如沙漠中的甘露,而要是撞见了杯具的UI套件,整个界面开发就有如梦魇了。
Android的UI框架,最核心的,是 资源 Layout 体系,然后,通过完善的 控件库 ,简明的接口设计,进一步帮助开发者,能够最快的搭建自己需要界面(听到这里,Symbian同学开始钻土...)。

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_parentwrap_content,这样的概念性的大小。丈量并设定控件的位置,是通过两步来进行的。
第一步是 measure。它传入此控件的width/height信息,控件会根据自己的参数,计算出真实需要的width/height,然后调用 setMeasuredDimension方法,缓存成成员变量,留作后用。
在计算出大小之后,会进行另一个步骤, layout。在这个过程中,父控件会计算其上各个子控件的位置,从而完成整个大小和位置的确定流程。整个measure和layout的流程,都是自上到下,从树顶往叶子来推进的。
当开发人员需要自定义控件的时候,可能需要关注这些内容,通过重载 onMeasureonLayout方法,可以定义自己控件的丈量方式。

事件

在Android中,所有的按键,触屏等事件,都是从顶至下进行分发的。每个ViewGroup的对象,会维系一个 focused变量,它表示在这个父控件中具备focus的控件,当有按键时间发生的时候,会找到这个focused子控件,并传递给它。同理,触屏事件的分发也是类似,只不过和focus无关,父控件会遍历所有子控件,看看谁处于触碰位置,从而传递给谁。
另外还有一些事件,逻辑上并不是从顶至下发起的。比如,当你修改某个子控件的内容,使得该子控件的大小和内容都发生了变化,就需要进行控件的重排和重绘,这些操作不仅是子控件自己的事情,需要整个控件树上的所有控件都需要配合。在Android中,处理这类事情的实现策略是子控件维系一个 ViewParent对象,该对象象征着整个控件树的管理者,子控件产生影响整个控件树的事件时,会通知到ViewParent,ViewParent会将其转换成一个自顶向下的事件,分发下去。
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中。从而完成整个通信流程。









本文转自 duguguiyu 51CTO博客,原文链接:http://blog.51cto.com/duguguiyu/362229,如需转载请自行联系原作者
目录
相关文章
|
6月前
|
SQL 人工智能 移动开发
Android 遍历界面所有的View
本文讲述如何遍历获取页面中所有的view,并输出对应的id,textview文本内容,imageview实际大小及设置的图片大小。 可用于检测android应用中的大图。
|
2月前
|
Android开发 数据安全/隐私保护
【Android Studio】简单的QQ登录界面
【Android Studio】简单的QQ登录界面
|
4月前
|
XML Java 调度
Android App网络通信中通过runOnUiThread快速操纵界面以及利用线程池Executor调度异步任务实战(附源码 简单易懂)
Android App网络通信中通过runOnUiThread快速操纵界面以及利用线程池Executor调度异步任务实战(附源码 简单易懂)
30 0
|
4月前
|
XML Android开发 数据格式
Android Studio App开发实战项目之实现淘宝电商App首页界面(附源码,可用于大作业参考)
Android Studio App开发实战项目之实现淘宝电商App首页界面(附源码,可用于大作业参考)
73 0
|
4月前
|
XML Java Android开发
Android Studio App自定义控件中视图的构造和测量方法讲解及实战(附源码 实现下拉刷新功能 超详细必看)
Android Studio App自定义控件中视图的构造和测量方法讲解及实战(附源码 实现下拉刷新功能 超详细必看)
41 1
|
7月前
|
Android开发
Android获取已连接wifi的热点信息(上位机开发学习之多个界面切换编程)
Android获取已连接wifi的热点信息(上位机开发学习之多个界面切换编程)
183 0
|
9月前
|
存储 编解码 缓存
|
10月前
|
XML 编解码 架构师
Android智能平板应用,界面适配的另一种轻量级方法
Android智能平板应用,界面适配的另一种轻量级方法
|
11月前
|
XML Java Android开发
每日记录自己的Android项目(一)——UI界面
由ViewBinding绑定好XML布局和根布局和标题栏。 还有个字段 private AppBarConfiguration appBarConfiguration;
75 0
|
12月前
|
Java 数据库 Android开发
Android MTK平台 客制化系统来电界面(屏蔽 InCallUI 提供接口给客户自行展示来电去电页面)
Android MTK平台 客制化系统来电界面(屏蔽 InCallUI 提供接口给客户自行展示来电去电页面)
155 0