界面构造

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中。从而完成整个通信流程。

深入Android 【六】 —— 界面构造相关推荐

  1. 深入理解Android 之界面构造

    UI界面,对于每个应用而言,是它与用户进行交互的门脸.好的门脸,不只是是要亮丽可人,最好还能秀色可餐过目不忘,甚至还应该有涵养有气质,彬彬有理温柔耐心. 对于开发者来说,锻造这样的面容,不但需要高超的 ...

  2. android用户引导页,android欢迎界面引导页

    android欢迎界面是所有程序开始的一个简短的自我介绍,让用户能够通过简单的描述和图片信息更好的了解软件,对用户体验效果非常的重要.这里我会使用VIewPager做一个欢迎界面. 1设计背景图片 根 ...

  3. Xamarin Android设置界面提示类型错误

    Xamarin Android设置界面提示类型错误 错误信息:Integer types not allow (at 'padding' with value '10') Android界面属性的长度 ...

  4. Android微信界面的设计

    Android微信界面的设计   [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/51777792 微信6.0主界面: (1 ...

  5. Android典型界面设计(3)——访网易新闻实现双导航tab切换

    一.问题描述 双导航tab切换(底部区块+区域内头部导航),实现方案底部区域使用FragmentTabHost+Fragment, 区域内头部导航使用ViewPager+Fragment,可在之前博客 ...

  6. android注册界面高级,Android用户注册界面简单设计

    本文实例为大家分享了Android用户注册界面的设计,供大家参考,具体内容如下 I. 实例目标 设计一个用户注册界面,在其中要使用到一些基础控件,如 文本框.编辑框.按钮.复选框等控件 II. 技术分 ...

  7. android+主界面所有应用程序图标添加统一背景主题,Android 4.0替Launcher主界面所有应用程序图标添加统一背景主题...

    当前位置:我的异常网» Android » Android 4.0替Launcher主界面所有应用程序图标添加 Android 4.0替Launcher主界面所有应用程序图标添加统一背景主题 www. ...

  8. android中注册用户界面,Android用户注册界面

    搜索热词 先给大家展示下界面效果图,感觉满意,请参考实现代码. Main.xml源码 android:layout_width="match_parent" android:lay ...

  9. android启动界面修改工具,Android 系统界面调节工具使用及功能

    Android 系统界面调节工具(Android System UI Tuner)是个隐藏功能,里面有一些实验性功能,可以辅助平时开发. 1. 打开 系统界面调节工具是个隐藏功能,打开他说简单也简单, ...

最新文章

  1. 体验Windows 7的Superbar
  2. eclipse java 7_在Eclipse中编程Java 7
  3. python项目NoReverseMatch: Reverse for ‘topic‘ with arguments ‘(‘‘,)‘ not found解决方法
  4. 【解惑】这么多技术我该怎么学
  5. 一个亿万富翁和一个陌生人的换钱计划
  6. linux 端口qos,linux的qos机制 - cgroup篇 (2)
  7. butter滤波器是iir吗_IIR低通滤波器求改
  8. 过磅系统_简讯:崇义商砼公司开展无人值守过磅系统业务培训等二则
  9. php毛玻璃,毛玻璃的性质及功能特点
  10. Java获取外网ip地址
  11. 莫迪:“智能城市”可协助解决城市化快速扩张挑战
  12. python下载m3u8视频_Python 下载m3u8格式的视频
  13. 如何设置和解除PDF文件保护?
  14. Pl/Sql 导入dmp文件时窗口一闪而过
  15. 1278 相离的圆(任务调度,贪心)
  16. 第十四节 OSAL工作原理
  17. 【模块间的通讯】数据接口及通讯代理系统架构
  18. 面对新时代挑战,2019维谛技术峰会全面呈献硬核策略
  19. JAVA实现活动安排
  20. Go语言版黑白棋(九):吃子

热门文章

  1. mysql 实验论证 innodb表级锁与行级锁
  2. Gold Balanced Lineup - poj 3274 (hash)
  3. C# HashTable 使用用法详解
  4. linux驱动开发的经典书籍
  5. mysql 和 oracle 的一些区别
  6. 限时分享:产品经理面试高频考题及答案
  7. 腾讯产品面试题 | 如何把剃须刀卖给张飞?
  8. 【干货】从国外知名网站看用户体验4个基本标准
  9. 【干货】移动互联网时代的零售店面转型之道
  10. 如何在Github打造你的爆款开源项目