当前位置:操作系统 > 安卓/Android >>

Android ApiDemos示例解析(63):Graphics->Density

支持Android系统的手机的种类很多,每种手机的屏幕大小和分辨率可能有所不同(屏幕像素密度),Android系统提供了方法在这些有着不同大小,屏幕像素密度的手机上自动调整显示界面的布局和大小,同时Android也提供了相关API允许开发者针对不同的屏幕大小和显示密度来控制UI以便应用在不同配置的设备屏幕上都有良好的显示效果。

尽管Android系统提供了屏幕自适应功能可以解决大部分不同屏幕UI显示的问题,应用还是需要做一些能支持不同屏幕配置的工作,这样可以给最终用户在不同屏幕配置下都取的很好的用户体验。

在介绍本例之前,先解释一些术语:

屏幕大小(Screen Size): 设备屏幕的物理尺寸(对角线长度),比如3寸屏,4寸屏。为简单起见,Android将屏幕大小分成四类: small (小尺寸), normal(正常尺寸), large(大尺寸), extra large(超大尺寸)。

屏幕显示密度(Screen Density): 单位尺寸显示的像素数目。通常采用dpi 为单位( 点数/英寸)。比如“高密度“的屏幕在单位尺寸内显示的像素数目大于”低密度“的屏幕。为简单起见,Android也将屏幕显示密度(后面简称屏幕密度或密度)分为low(低密度), medium(中等密度),high (高密度), extra high(超高密度)。

屏幕纵横方向(Orientation): 从用户角度看,显示屏幕可以为横向(landscape)或是纵向(portrait) ,用户在应用运行时可以改变屏幕的纵向或是横向。

屏幕分辨率(Resolution): 屏幕支持显示的像素总数。在谈支持多种屏幕配置上,应用通常不之间操作屏幕的分辨率,而是要关心屏幕的大小和密度。

密度无关像素(Density-independent pixel– dp) : 在定义Layout是使用到的与设备无关虚拟像素单位。dp 定义为 160dpi 屏幕上一个像素大小。 160dpi 被Android系统认为是“中等密度”的屏幕。使用dp为单位时,当应用运行时,Android会自动根据屏幕实际的大小和密度放大或是缩小Layout中的控件达到界面屏幕自适应的效果。 有 dp 值到实际像素值的换算很简单: px = dp * (dpi /160) 。

Android支持的屏幕范围 Android系统从1.6开始可以支持多个屏幕大小和屏幕密度,上面说过Android将屏幕大小和屏幕定义都分为四类,采用第一代Android手机T-Mobile G1的屏幕(HVGA)做为基准。下图显示了屏幕大小和屏幕定义的一个粗略分类:
\

应用可以通过提供备选资源的方法来支持不同的屏幕配置。典型的做法是为不同屏幕大小或屏幕密度提供不同的的Layout和图片资源。Andorid系统运行时可根据当前屏幕的实际配置来选择合适的Layout和资源显示用户界面,通常并不需要为每个屏幕大小和屏幕密度的组合都提供不同的Layout和资源,Android 系统会非常“智能”的来处理不屏幕配置下界面的显示问题。

屏幕密度无关性(Density independence), 如果说应用具有“屏幕密度无关性”只的是应用的UI组件中不同的屏幕显示密度小其实际物理尺寸保持不变。

保持界面的实际物理尺寸非常重要,没有图,一个按钮在“低密度”屏幕上的物理尺寸比“高密度”屏上尺寸要大,下面两幅图显示了“不支持屏幕密度无关性”和支持“屏幕密度无关性”的显示效果:

\\

Android 系统采用下面两种方法来帮助应用实现“密度无关性”:

系统根据当前屏幕密度为采用dp 为单位的Layout 组件自动缩放以适应屏幕。
系统根据当前屏幕密度为Drawable 资源进行缩放。
因此在大部分情况下,可以通过使用dp为单位给Layout中的组件指定大小,和正确使用”wrap_content”属性来达到“屏幕密度无关性”。但对应bitmap 资源来说,自动的缩放有时会造成放大缩小后的图像变得模糊不清,这是就需要应用为不同屏幕密度配置提供不同的资源:为高密度的屏幕提供高清晰度的图像等。

如何支持多屏幕配置

Android系统本身自动可以支持屏幕自适应,但有时也需要应用提供屏幕配置相关的资源以达到更好的用户体验:

为不同屏幕大小提供不同的Layout.
为不同屏幕密度提高不同的bitmap图像资源。
Android系统运行时根据当前屏幕配置选择合适的Layout和资源,如果对于的屏幕配置没有提供备选资源,则选用缺省资源进行缩放。

下表列出了Android屏幕配置可能的组合:

来看看apidemos中定义的资源目录:

 \

比如对于drawable  来说, drawable 不带任何后缀,为缺省drawable 资源, drawable-hdpi 为高密度屏幕使用的drawable资源, drawable-ldpi 为低密度屏幕使用的drawable 资源等。

同样values 定义了多种不同配置下使用的资源。

对应不同屏幕密度下的Bitmap资源定义(.png. .jpg, .gif ,.9.png)一个原则上使用 3:4:6:8的比例来为四种不同屏幕密度提供图像资源,比如对于一个“中等密度”下像素大小为48X48的资源,

Low-density:  36X36
Medium-density: 48X48
High-density: 72X72
Extra high-density: 96X96

\
关于Density的一些额外的考虑

本节内容对于大部分应用不重要,除非你的应用在不同屏幕配置时显示上出了问题。

为了更好的理解在应用绘制图形时如何支持不同的屏幕密度配置,你应该知道下面由Android系统提供的一些支持:

Pre-scaling of resources (如bitmap drawable 资源)

Android系统根据当前设备屏幕配置不进行缩放选取设备配置相关的资源(比如对于高密度屏幕选取drawable-hdpi目录下的Drawable资源)。如果没有找到当前屏幕配置对应的资源,Android使用缺省资源(在drawable 目录下的资源)放大或是缩小以适应屏幕。Android应用认为缺省资源(比如drawable 等不带后缀的目录下)是对应于基准屏幕配置(mdpi)的资源。pre-scaling 意思就是Android系统为当前屏幕密度自动缩放Bitmap来适应屏幕的过程。

此时,如果你需要知道这些pre-scaled资源的大小,Android系统返回的是缩放之后的大小,比如对应于mdpi 下50X50像素大小的图像在hdpi屏幕下会放大到75X75像素大小,此时查询图像大小返回值为75X75. 如果你不想让Android对一些资源进行pre-scaling,可以将这些资源放在带nodpi后缀的目录下:比如 /res/drawable-nodpi。

Density 例子中的 no-dpi resource drawable 显示如下:

 \

像素大小和坐标的自动缩放

一个应用也可以通过在Manifest文件中将android:anyDensity设为”false”或在代码中将bitmap的isScaled设为false关闭pre-scaling 。在这个情况下,Android系统会自动缩放以pixel为单位的的像素值和坐标。结果使得在不同屏幕大小的设备上仍可以显示和基准屏幕下类似的物理尺寸大小。这时如果需要返回Bitmap的大小,系统返回的是缩放后的像素值,而非实际物理像素值。

大部分情况“不应该关闭pre-scaling”,而是通过提供屏幕配置相关资源来支持多种屏幕配置。

运行时缩放Bitmap

如果应用在内存中动态创建一个Bitmap对应,Android系统会认为这个Bitmap对应于基准屏幕配置(中等密度)。缺省情况下,如果在屏幕上显示这个Bitmap,Android系统会自动缩放以适应当前屏幕。 可以使用setDensity为Bitmap 设置显示密度。

如果使用BitmapFactory来创建Bitmap对象,可以使用BitmapFactory.Options来定义Bitmap的属性,如果将inScaled设为false,则会关闭pre-sacling.

下图为Density例子 显示 pre-scale 和auto-scale 显示 low (120), medium (160), high (240) 的图像中高密度屏上显示的效果:

 \

注意这个例子的Title : Density:High ,可能你的设备运行时结果不一样:

[java]
this.setTitle(R.string.density_title); 

this.setTitle(R.string.density_title);标题的资源为R.string.density_title ,它在values ,values-large ,values-small中用不同的定义, 在应用运行时,Android系统会根据当前屏幕配置选取合适的资源,你可以多创建几种不同大小的模拟器,看看结果会有所不同,由此也可以理解本例和Android选取资源的机制。

下表给出模拟器支持的不同屏幕大小和密度的组合:

 

\

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,