0 引 言

       2007 年11 月,Google 公司发布基于Linux2.6 内核的移动终端操作系统- Android, 由于其开源性,得到很多手机厂商的追捧和应用开发者的青睐。近年来智能手机发展迅速,运行速度、存储容量和可靠性等指标有了显着提高[1],当今的智能手机用户对应用软件的舒适性和美观性有了更大的期望,应用程序界面友好性已经越来越重要。但是由于Android 的开源性,硬件厂商屏幕分辨率不统一,据统计目前市场上Android系统手机的分辨率有10 余种,分辨率分布如此广泛使得开发者在处理多分辨率适应方面遇到了不少难题。文章首先介绍Android 平台的系统架构及资源管理方法,之后介绍目前开发者在处理多分辨率时采用的方法,而后重点分析Android平台资源加载机制并且结合实例给出多分辨率的处理步骤及技巧,最后介绍测试多分辨率效果的方法。
1 Android 平台简介
       Android 是一个包括操作系统、中间件和关键应用的移动设备软件堆[2],Android 系统和其他系统一样,采用分层的架构。由下至上依此为Linux 操作系统和驱动、程序库及Android 运行时环境、应用程序框架层、应用层。 Android 应用程序的基本组件有Activity、Intent、BroadcaSTReceiver、Service 四种,各个组件的配置信息以及权限管理、版本管理等配置信息都保存在AndroidManifest.xml 中。
1.1 Android 应用程序资源管理
       手机界面上加载的图片是Android 资源的一种,除此之外还有XML 资源(anim.xml layout.xml 等)以及原数据文件( 音视频文件等)[3].新建一个HelloAndroid 的Android 应用程序,默认生成的文件架构包含src,gen,assets,res 等文件夹,以及AndroidManifest.xml 配置文件。src 文件夹中保存的是Android 源代码,res 文件夹代表应用程序需要使用到的资源文件,gen 包中包含R.java 文件。Res 文件夹中包含的所有资源文件都对应在R.java 中。
       当开发者在res/ 目录中任何一个子目录中添加相应类型的文件之后,ADT 会在R.java 文件中相应的匿名内部类中国自动生成一条静态int 类型的常量,对添加的文件进行索引。
       Android 系统采取这种架构使视图等资源文件与控制代码分离,实现松耦合。然而可以使用R.java 文件在代码中对相应的资源文件进行存取,灵活操作。
1.2 一般多分辨率处理方法及其缺点
1.2.1 图片缩放

       基于当前屏幕的精度,平台自动加载任何未经缩放的限定尺寸和精度的图片。如果图片不匹配,平台会加载默认资源并且在放大或者缩小之后可以满足当前界面的显示要求。例如,当前为高精度屏幕,平台会加载高精度资源(如HelloAndroid中drawable-hdpi 中的位图资源),如果没有,平台会将中精度资源缩放至高精度,导致图片显示不清晰。
1.2.2 自动定义像素尺寸和位置
       如果程序不支持多种精度屏幕,平台会自动定义像素绝对位置和尺寸值等,这样就能保证元素能和精度160 的屏幕上一样能显示出同样尺寸的效果。例如,要让WVGA 高精度屏幕和传统的HVGA 屏幕一样显示同样尺寸的图片,当程序不支持时,系统会对程序慌称屏幕分辨率为320×480,在(10,10)到(100,100)的区域内绘制图形完成之后,系统会将图形放大到(15,15)到(150,150)的屏幕显示区域。
1.2.3 兼容更大尺寸的屏幕

       当前屏幕超过程序所支持屏幕的上限时,定义supportsscreens元素,这样超出显示的基准线时,平台在此显示黑色的背景图。例如,WVGA 中精度屏幕上,如程序不支持这样的大屏幕,系统会谎称是一个320×480 的,多余的显示区域会被填充成黑色。

1.2.4 采用OpenGL动态绘制图片
       Android 底层提供了OpenGL 的接口和方法,可以动态绘制图片,但是这种方式对不熟悉计算机图形学的开发者来讲是一个很大的挑战。一般开发游戏,采用OpenGL 方式。

1.2.5 多个apk 文件
       Symbian 和传统的J2ME 就是采用这种方式,为一款应用提供多个分辨率版本,用户根据自己的需求下载安装相应的可执行文件。针对每一种屏幕单独开发应用程序不失为一种好方法,但是目前Google Market 对一个应用程序多个分辨率版本的支持还不完善,开发者还是需要尽可能使用一个apk 文件适应多个分辨率。
2 多分辨率处理方案详解
2.1 基本术语介绍
2.1.1 屏幕尺寸

       真正的物理尺寸,屏幕对角线的长度,单位是英寸。为了简化起见,Android 把支持的所有物理尺寸分成了4 组:small,normal, large, extra large.


2.1.2 屏幕密度Density
       一定物理范围的像素的个数,单位通常是dpi(dots perinch),即每英寸的点数。密度较低的屏幕,在长和宽方向都只有比较少的像素,而高密度的屏幕通常则会有 
很多,甚至会非常非常多的像素排列在同一区域。
       例如一个低分辨率屏幕相对于高分辨率屏幕在一定的物理区域内包含的像素点要少。为了简化起见,Android 将所有的屏幕密度分成四组:low, medium,high 和extra high.

2.1.3 方向Orientation
       从用户视角来看的屏幕的方向,Portrait 纵向和Landscape 横向。
2.1.4 分辨率Resolution
       分辨率是指屏幕上拥有的像素的总数,通常使用“宽度×长度”表达。 虽然大部分情况下分辨率都被表示为“宽度×长度”,但分辨率并不意味着屏幕比 例。 (决定屏幕比例的是物理长度和物理宽度) ,通常,应用程序并不直接处理分辨率。


2.1.5 密度无关像素

       密度无关像素dp: Android 平台中虚拟的像素单位,定义成一种密度无关的形式,像素px 和dp 的转换公式为 px =dp*(dpi/160)。在界面开发中应使用dp 作为像素单位,从而保证在不同的屏幕密度上控件所占的实际px 因密度而自动调整。

2.1.6 Retina屏幕

        Retina屏幕是一种超高像素和越高密度的液晶屏。相对于以前的iPhone ,iPhone4 的屏幕增加了4倍的像素数量,它将960*640的分辨率压缩到和前代iPhone相同物 理尺寸(3.5英寸)的显示屏内。 
       为了做到两代iPhone在显示大小上看起来一致,该屏幕的像素密度必须达到326像 素/英寸。更精密的显示技术使人眼已难以分辨单个的像素,这使文字特别清晰, 画质特别生动鲜活。 


2.2 手机屏幕的分类


       Android 采用两种标准对屏幕进行分类。按照屏幕尺寸分为四组small, normal, large, extra large;按照屏幕密度分为四组 low, medium ,high 和extra high,其分界线如图1所示。


图1 Android 中的屏幕分类
       为了优化程序UI,让其适应多种分辨率并能清晰显示,一般情况下需要为不同屏幕大小密度提供不同的图片文件和对应的布局文件,在运行的时候,Android 系统会根据当前设备的屏幕大小及密度等信息,选择加载其中一套匹配的资源加以运行,从而达到适应多分辨率的效果。

2.3 设计

2.3.1 设计基准

         结合种种因素 ,最终定义以中密度的正常屏幕(HVGA )为设计基准。 


        HVGA (Half-size VGA)即VGA(640*480)的一半,分辨率为(480*320)。 
       它是用于各种各样的PDA设备,首先是2002年的索尼Clie PEG - NR70 ,黑莓手机 谷歌手机也有HVGA的,iPhone也是HVGA设备。全球第一款Google手机,T- Mobile G1配备有3.2英寸HVGA (320*480 )分辨率的全觌控式屏幕。 

QVGA 240*320像素
VGA 640*480像素
WVGA 800*480像素
HVGA 480*320像素 

2.3.2 UI设计

       从开发角度讲,应用程序会根据3类Android手机屏幕提供3套UI布局文件,但是相应界面图标也需要提供3套,如下表所示:

Icon Type

Standard Asset Sizes (in Pixels), for Generalized Screen Densities

 

Low density screen (ldpi)

Medium density screen (mdpi)

High density screen (hdpi)

Launcher

36 x 36 px

48 x 48 px

72 x 72 px

Menu

36 x 36 px

48 x 48 px

72 x 72 px

Status Bar

24 x 24 px

32 x 32 px

48 x 48 px

Tab

24 x 24 px

32 x 32 px

48 x 48 px

Dialog

24 x 24 px

32 x 32 px

48 x 48 px

List View

24 x 24 px

32 x 32 px

48 x 48 px


2.4 Android 支持多分辨率原理及步骤

       由以上分析,默认的加载方式都不能很好地适应不同的分辨率,Android 从1.6 开始支持多种分辨率的处理,原理简而言之就是根据屏幕参数,动态加载资源文件。在Android 项目文件结构中,drawable 文件夹下包含三个子文件夹,分别为drawable-hdpi, drawable-mdpi, drawable-ldpi, 分别存放hdpi,mdpi,ldip 的位图。应用程序运行时,Android 系统会根据当前设备的屏幕大小、分辨率、屏幕密度、方向、长宽比等信息,选择相应文件夹进行加载。Android 配置修饰符的定义规则如下:
       1)在res 文件夹下新建目录,命名为<resources_name>-<qualifier> 这种格式,其中<resources_name> 为标准资源名称,例如drawable 或者layout;<qualifier> 即修饰符,指定对应的屏幕参数,比如normal/small/large,hdpi/mdpi/ldpi,land/port,long/notlong 等。
       2)在步骤1 新建的文件夹中存入相应的资源,比如位图资源或者layout 资源,资源文件的名字必须与默认资源文件的名字相同。例如:


       3)Android 系统支持多分辨率的机制离不开Android-Manifest.xml 文件的supports-screen 元素,若应用程序要适应多种分辨率,需要将anyDensity 设置为true.
2.5 界面设计技巧
       前面的部分已经详细讲解了如何架构应用程序使其更好地适应多种分辨率屏幕,此外,在界面设计和控制中我们还应该掌握一些原则或者技巧,从而使应用程序界面友好、适应性强。
       1)在XML layout 文件中定义长度的时候,最好使用wrap_content,fill_parent, 或者dp 进行描述,这样可以保证在屏幕上面展示的时候有合适的大小。例如,一个view layout_width="100dip",在 HVGA@160 density 的设备上显示100 个px,而在 WVGA@240 density 的设备上显示150 个px,但是所占的物理尺寸时相同的。
       2)在Activity 或者其他控制视图加载的代码处,不要使用像素单位的硬编码。
       3)不要使用AbsoluteLayout.绝对布局是由AndroidUI toolkit 提供的布局容器中的一种。但是与其他layout 不一样的是,AbsoluteLayout 使用固定的位置表示,使得在不同的屏幕上面显示效果不好,因此AbsoluteLayout 在sdk1.6 及以后的版本中被弃用了。
       4)为不同屏幕密度的手机,提供不同的位图资源,可以使得界面清晰无缩放。
3 多分辨率兼容性测试方案
      在产品发行之前,要在所有的目标手机上进行全面的测试。Android SDK 包含了一套测试多分辨率的机制。可以自己定制avd 作为应用程序的测试环境,avd 会模拟真实机器的屏幕大小和密度。例如图2 为模拟器的列表,可以将程序运行在这四个模拟器中进行多分辨率的测试。

图2 虚拟机列表
4 结论
       本文介绍Android 平台的体系架构和分辨率相关的术语,详细论述资源加载原理和多分辨率处理的详细流程,最后给出了测试应用程序是否适应多种分辨率的方法。结合本人实践经验进行讲述,内容深入浅出,较完整地论述了如何使应用程序尽可能多地适应多种分辨率屏幕。


参考资料:

Android平台的多分辨率屏显设计及其兼容性测试

玩转Android多分辨率规格的界面设计.pdf

Android手机分辨率基础知识(DPI,DIP计算)

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐