【官网翻译】Android屏幕适配从原理到最佳实践(很全的教程)

原文:http://developer.android.com/intl/zh-cn/guide/practices/screens_support.html

翻译还比较粗糙,有一些地方难免不太通顺,而且文档难免繁琐和复杂,如果想看精简一点的移步:http://blog.csdn.net/program_thinker/article/details/41806135


Android运行在各种不同屏幕尺寸和密度的设备上,对于应用程序,Android系统提供了一个一致的跨设备的开发环境并且为适应不同屏幕处理绝大多数的事情。同时,为了应对更多特殊的屏幕,系统提供了各种API来优化你的应用程序界面。


虽然系统做了很多的扩展和调整,使你的应用程序能够在不同的屏幕上工作,但是你也应该做出努力,以优化在不同的屏幕大小和密度设备上的应用程序的表现。在此过程中,你最大程度的为所有设备增强用户体验,让用户体验到你的程序是为他们设备而作,而不仅仅是拉伸以适应设备屏幕。


按照文档中描述的行为,你可以使用一个apk文件创建提供支持所有屏幕配置并且显示正常的应用程序。


注意:本文档中信息假定你的应用程序为Android1.6(API 4)以及更高的版本,如果你的应用程序支持Android1.5或者更低,请写阅读Android1.5的策略。

此外,要注意Android3.2引入了新的API,让你能够为支持不同屏幕尺寸更精确控制使用的布局资源来构建你的应用程序。这些新功能是特别重要的,如果你正在开发对于平板电脑的应用程序,请参阅有关声明的平板布局Android3.2部分。


屏幕支持的概述

本节提供了Android多屏幕支持的概述,包括:API介绍,屏幕配置,总结系统使用的术语和概念,以及屏幕底层的概述


术语与概念


屏幕尺寸
实际的物理尺寸,测量屏幕的对角线。
为简单起见, Android中的所有实际的屏幕尺寸分为四个广义大小:小,正常,大,和超大。

屏幕像素密度
屏幕的物理区域内的像素的数量:通常被称为dpi(每英寸点数) 。例如,在给定的物理区域内一个“低”密度屏幕比 “正常”或“高”密度屏幕具有较少的像素。为简单起见, Android中的所有实际的屏幕密度分为六个广义密度:低,中,高,超高,超超高,超超超高。

方向

从用户的角度看到的屏幕方向。一般为横向或纵向,即屏幕的宽高比。注意,不仅要关注不同的设备在缺省情况下的屏幕方向。同一设备当用户旋转时,应用程序的屏幕方向也需要关注。


分辨率

在屏幕上的物理像素的总数。当为多个屏幕添加了支持,应用程序不直接与分辨率相关:应用程序应只能与屏幕大小和密度有关,和指定的广义的大小和密度基有关。


密度无关像素(DP)

虚拟像素单元。在定义UI布局的时候,你应当使用与密度无关的方式来表示布局尺寸或者位置

密度无关的像素相当于在一个160dpi屏幕上的一个物理像素。这是一个假定在“中等”密度屏幕的基线密度。在运行时候,系统透明的处理任何缩放的DP单位,根据需要转化成屏幕的实际密度。dp的转化屏幕实际像素比较简单:px = dp * (dpi / 160)。例如,一个240dpi的屏幕上,1dp等于1.5的物理像素。定义你的应用程序UI的时候,你应该总是使用dp单位,以确保在不同密度的屏幕UI的正确显示


屏幕支持的范围

从Android 1.6 ( API 4 )开始, Android提供了多种屏幕尺寸和密度,反映了多种不同的设备可能支持屏幕配置。您可以使用Android系统的功能来优化您应用程序的用户界面。对于每个屏幕配置,确保您的应用程序,不仅能够正常呈现,而且提供了最佳的用户体验。

为了简化您设计针对多个屏幕的用户界面的方法,Android把实际的屏幕尺寸和密度分成如下范围:
一组(四个)广义大小:小,正常,大和超大
一组(六种)广义密度:
ldpi (低) 〜 120dpi
mdpi (中) 〜 160dpi
hdpi(高) 〜 240dpi
xhdpi (超高) 〜 320dpi
xxhdpi (超超高) 〜 480dpi
xxxhdpi (超特超高) 〜 640dpi


广义的尺寸和密度围绕一个正常大小和mdpi密度的基准配置。这个基准配置是基于第一个Android设备的屏幕,型号 T- Mobile G1 ,它有一个HVGA屏幕(直到安卓1.6 ,这是Android的唯一支持的屏幕配置) 。

每个广义尺寸和密度跨越一系列实际屏幕尺寸和密度。例如,两个设备都声明了正常的屏幕大小但手工测量的实际的屏幕尺寸和纵横比可能略有不同。同样地,两个设备都声明了hdpi的画面密度但实际的像素密度可能也略有不同。安卓为应用程序抽象这些差异,根据你提供UI设计的广义大小和广义密度,让系统按必要的情况做出调整。图1示出了如何将不同的尺寸和密度大致地分类为不同的尺寸和密度。


图1.Android的粗略的广义屏幕大小和密度 。

当你设计你的用户界面以适配不同的屏幕尺寸,你会发现每一个设计都需要一个空间的最小量。所以,每个以上的广义尺寸具有由系统定义的相关联的最小分辨率。这些最小尺寸以“DP ”为单位,在定义你的布局时你应该使用dp为单位,它允许系统不用担心屏幕密度改变

  • 超大屏幕是至少960dp X 720dp
  • 大屏幕至少640dp X 480dp
  • 正常屏幕至少470dp X 320dp
  • 小屏幕至少426dp X 320dp
注意:这些最小的屏幕尺寸在Android3.0之前都没有得到很好的定义 ,所以你可能会遇到一些设备在标准和大之间的错误分类。这也是基于屏幕的物理分辨率,因此可以跨设备,例如一款1024x720平板电脑实际上由于系统栏而减少了提供给应用程序的空间。

为不同的屏幕尺寸和密度优化您的应用程序的UI,可以为任何广义大小和密度提供备选资源。通常情况下,你应该为不同的屏幕尺寸提供可供选择的布局和为不同的屏幕密度提供备选的位图图像。在运行时,系统根据当前设备屏幕的大小和密度为您的应用程序使用适当的资源。


你不需要对屏幕尺寸和密度的各种组合提供备选的资源。系统提供了强大的兼容功能,可以处理你的应用程序在大多数设备屏幕上工作,前提是你使用能够调整的技术(如最佳实践说明,下同)实现您的UI。


注意:定义一个设备的屏幕尺寸和密度的特性是彼此独立的。例如,一个WVGA高密度屏幕被认为是一个正常大小的屏幕,因为它的物理尺寸和T-Mobile G1大致相同( Android的第一台设备和基准屏幕) 。另一方面,一个WVGA中密度屏幕被认为是一个大尺寸屏幕。虽然它提供了相同的分辨率(像素数相同) ,所述的WVGA中密度屏幕具有较低的屏幕密度,这意味着每个像素在物理上是较大的,因此,整个屏幕比基线(正常大小)的屏幕大。


屏幕密度独立

当你的应用实现了“密度独立”时,从用户的角度看,在不同密度屏幕显示的用户界面元素都保持了对应的物理尺寸(译者注:就是用户看起来不同屏幕体验都一样,这话说成这样真是绕)


维持密度独立性是很重要的,因为如果没有它,一个用户界面元素(如按钮)显示在低密度屏幕上比显示在高密度屏幕上在物理上更大。这样的密度有关大小的变化可能会导致你的应用程序的布局和可用性问题。图2和3表明应用程序提供或者不提供密度独立显示的差异。


图2:密度不独立的应用程序,对不同密度屏幕的显示效果


图3:密度独立的应用程序,对不同密度屏幕的显示效果


Android系统可以帮助您的应用程序实现密度独立两种方式:

  1. 系统为适合当前屏幕密度伸缩dp单位
  2. 系统根据当前屏幕密度扩展资源到合适的大小,如果需要的话
在图2中,文本视图和位图资源的拉伸是以像素(px)为单位的,所以我们看到的界面元素在低密度屏幕在物理上显示更大和高密度屏幕物理上显示更小。这是因为,尽管实际的屏幕尺寸可以是相同的,在高密度屏幕上具有每英寸更多的像素。在图3中,布局尺寸是由密度无关像素( dp)指定。因为密度无关的像素是以一个中等密度的屏幕为基线的,所以它和图2中具有中等密度屏幕上看起来相同。对于低密度和高密度的屏幕,系统分别向下和向上的扩展密度无关像素值,以适应对应屏幕。

在大多数情况下,你可以确保你的应用程序密度的独立性只需通过密度无关像素( dp单位)或“ WRAP_CONTENT ”来规定所有的布局尺寸值。然后,系统根据当前屏幕的密度相应的缩放因子酌情扩展位图以显示在适当的大小。

然而,你可能在上面的截图中看到,位图缩放可能会导致模糊或像素化的位图。为了避免这些问题,就应该针对不同的密度提供备选位图资源。例如,你应该为高密度显示屏提供更高分辨率的位图,系统将使用这些代替专为中等密度的屏幕的位图。以下部分介绍了更多关于如何为不同的屏幕配置提供备选资源。

如何支持多屏幕
Android的多屏幕支持的基础是它能够根据当前屏幕配置以适当的方式管理提出申请的布局和位图渲染能力。系统处理的大部分工作是以适应屏幕尺寸/密度缩放布局和扩展位图以适应屏幕像素密度。但是,为了更加妥善地处理不同的屏幕配置,你也应该:

在manifest中显示声明应用程序支持的屏幕尺寸清单
通过声明应用程序支持的屏幕尺寸,可以确保你支持的屏幕的设备可以下载你的应用。通过声明支持不同屏幕的尺寸还可以影响系统如何在大屏幕上绘制你的应用程序,特别的,应用程序是否在屏幕兼容模式下运行。声明应用程序支持的屏幕尺寸,你应该在你的manifest文件包括<supports-screens>元素。

为不同的屏幕尺寸提供不同的布局
默认情况下, Android系统重新调整你的应用程序布局以适应当前设备的屏幕。在大多数情况下,这工作的很好。但在有些情况下,你的UI可能看起来不那么好,可能需要调整不同的屏幕尺寸。例如,在大屏幕上,您可能需要调整一些元素的位置和大小以充分利用屏幕空间的优势,或者在一个较小的屏幕上,你可能需要调整大小,使一切都可以容纳在屏幕上。
根据配置限定符,你可以用它来提供大小的特定资源,比如小,正常,大和超大 。例如,超大屏幕布局应该在文件夹layout-xlarge /下面 。
从Android 3.2 ( API等级13 )起,上述尺寸组已过时,应改用sw <n > dp配置限定符来定义你的布局资源所需的最小可用宽度。例如,如果你的平板电脑的布局至少需要600dp屏幕宽度,你应该把它放在文件夹layout-sw600dp /下 。在有关平板布局的声明在Android 3.2节进一步讨论。

为不同的屏幕密度提供不同的位图资源
默认情况下, Android的扩展位图资源包括(.png,.jpg和.gif文件)和九补丁资源( .9.png文件) ,它们以适当的物理尺寸呈现在每个设备上。例如,如果你的应用程序只为基准屏幕(中屏幕像素密度mdpi)提供的位图资源 ,那么在高密度屏幕上的时候系统会扩展它们,并在低密度屏幕上的时候系统缩放它们。这个缩放可能会影响位图。为确保您的位图看起来是最好的,你应该包括不同屏幕密度和不同分辨率备选版本。
根据配置的限定符,你可以使用密度特定的资源,包括ldpi(低),mdpi(中),hdpi(高),xhdpi(超高),xxhdpi(超超高)和xxxhdpi(超超超高)。例如高密度屏幕位图资源应该放在文件夹drawable-hdpi/下
注意:drawable-xxxhdpi限定符仅需要提供给比xxhdpi设备上的launcher的图标,你并不需要为所有的应用程序提供xxxhdpi资源。
某些设备需要向上扩大25%的launcher的图标,例如如果你的最高密度的launcher的图标已经是xxhdpi的密度,在xxxhdpi上显得不那么清晰,那么最好提供xxxhdpi的绘制目录

注意:如果你不熟悉的配置限定符和系统如何使用这些备选资源,阅读提供备选资源(http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources)以获取更多信息。

在运行时,通过下列步骤系统确保当前屏幕的最佳可能显示:
1、系统采用了合适的备选资源
基于当前屏幕的尺寸和密度,系统使用应用程序提供的适合大小与密度相关的资源。例如,如果该设备具有高密度的屏幕,当应用程序请求绘制资源,系统寻找最匹配该设备配置的可绘制的资源的目录。根据现有的备选资源,hdpi限定符目录下的资源(如drawable - hdpi/ )可能是最好的匹配,因此系统采用这个目录中的资源进行绘制。
2、如果没有匹配的资源是可用的,则系统将使用默认资源向上或向下按需要缩放以匹配当前的屏幕尺寸和密度
“默认”资源是那些不具有标记的结构限定符。例如,在drawable/目录下的资源是默认绘图资源。系统假定默认资源被设计为基线屏幕大小和密度,这是一个正常的屏幕尺寸和中等密度。这样,系统为高密度屏幕向上放大缺省资源或者为低密度资源向下缩小资源。
然而,当系统正在寻找一个特定密度的资源,并且没有发现它在特定密度的目录中时,也不会总是使用默认资源。系统可改用其他密度相关的资源之一,为了缩放时提供更好的结果。例如,没有找一个低密度资源时,系统倾向于按比例缩减高密度版本的资源,因为系统可以很容易地根据0.5因子向下缩放高密度资源到低密度,并且产生更少的模糊,相比根据0.75的因子缩放中等密度的资源。

使用配置限定符
Android支持多种配置限定符,使你可以控制基于当前设备屏幕的特性,决定系统如何选择你的备选资源。一个配置限定符是在你的Android项目中可以追加到一个资源目录,并指定里面资源的设计配置的字符串。

使用配置限定符
1、在项目的res/目录下面创建一个新的目录,并使用以下格式命名:<resources_name>-<qualifier>。
  • <resources_name>是标准的资源名称(例如drawable或者layout)。
  • <qualifier>是表1的结构限定符。指定这些资源将被哪种屏幕配置使用(比如hdpi和xlarge)。
你可以一次使用多个<qualifier>标签,需要用破折号分隔。

2、在这个新的目录中保存相应的配置资源。资源文件必须与默认资源文件命名完全相同。
例如,xlarge是一个配置超大屏幕的限定符,当这个字符串添加到一个资源目录名中(如layout-xlarge),它指示系统,这些资源将在具有超大屏幕的设备中使用

表1:配置限定符,是你可以为不同屏幕配置特定的资源


例如,以下是资源的目录中,为不同的屏幕尺寸提供了不同的布局设计以及用于中密度,高密度及超高密度的屏幕的不同位图资源的应用程序的列表。
res/layout/my_layout.xml              // layout for normal screen size ("default")
res/layout-large/my_layout.xml        // layout for large screen size
res/layout-xlarge/my_layout.xml       // layout for extra-large screen size
res/layout-xlarge-land/my_layout.xml  // layout for extra-large in landscape orientation

res/drawable-mdpi/my_icon.png         // bitmap for medium-density
res/drawable-hdpi/my_icon.png         // bitmap for high-density
res/drawable-xhdpi/my_icon.png        // bitmap for extra-high-density
res/drawable-xxhdpi/my_icon.png       // bitmap for extra-extra-high-density
请注意,当Android系统选择将哪些资源在运行时使用时,它使用一定的逻辑来决定“最佳匹配”的资源。也就是说,你的限定符可以不必在所有情况下都匹配当前的屏幕配置。具体地,如果基于当前尺寸没有资源限定符很好的匹配的时候,系统会选择使用比当前屏幕小的资源(例如,如果必要的话,一个大尺寸屏幕会使用普通大小的屏幕资源) 。然而,如果唯一可用的资源比当前的大,如果没有其他的资源相匹配的设备配置,系统将不会使用它们(例如,如果所有的资源布局都标记XLARGE限定符,但设备是一个正常大小的屏幕)应用程序会崩溃。有关系统如何选择资源的更多信息,请阅读安卓如何查找最佳匹配资源(http://developer.android.com/guide/topics/resources/providing-resources.html#BestMatch)。
(译者注:经过实验,尺寸从下往上适配,密度从上往下适配)

提示:如果你有一些绘制资源不应该由系统扩大(也许是因为你在运行时对一些图像进行一些调整) ,你应该把它们放在nodpi配置限定符的目录。与此限定符相关资源被认为是密度无关,系统将不会扩展它们。

设计可备选的布局和绘图资源
你应该根据应用程序的需要创建备选资源。通常情况下,你应该使用大小和方向限定符来创建备选布局资源和使用密度限定符来创建备选位图绘制资源。

以下各节分别概述了你可能想使用的大小和密度限定符创建备选布局和绘图资源。

可选的布局
通常情况下,一旦你在不同的屏幕配置测试你的应用程序,你就会知道你是否需要为不同的屏幕创建屏幕尺寸替代布局。
  • 当在小屏幕上进行测试时,你可能会发现,你的布局并不完全适合在该屏幕上。例如,一排按钮未必适合在一个小屏幕设备上的宽度内。在这种情况下,你应该为小屏幕的替代布局调整按钮的大小或位置。
  • 当在一个特大屏幕上进行测试时,你可能会意识到你的布局不能有效地利用大屏幕,并且界面元素明显拉长以填补它。在这种情况下,你应该有针对性地重新设计一个超大屏幕的替代布局。虽然你的应用程序在不使用大屏幕替代布局的时候也应该正常工作,但在用户看来,你的应用程序看起来好像是为他们的设备专门设计是非常重要的。如果UI明显拉长,用户的应用体验更可能是不满意的。
  • 并且,与纵向测试相比,横向的时候,你可能会注意到,放置在纵向屏幕底部的UI元素应该放置在横向屏幕的右侧
总之,你应该确保你的应用程序布局:
  • 适合在小屏幕上(这样用户可以实际使用应用程序)
  • 对于更大的屏幕优化,充分利用额外的屏幕空间的优势
  • 优化横向和纵向两个方向
如果你的UI需要使用适配系统已经拉伸布局之后的位图(比如一个按钮的背景图片),你应该使用九补丁位图文件(Nine-Patch)。九补丁文件一种Png文件,它只在你指定二维区域内可拉伸。当系统需要按比例绘制位图时候,该系统拉伸九补丁位图,但拉伸的只有指定的地区。因此,你不需要为不同的屏幕尺寸提供不同的可绘制资源,因为九补丁文件可以调节到任何尺寸。但是,你应该提供九补丁文件的不同的屏幕密度替代版本。

可选的绘图资源
几乎每一个应用程序应该有不同的屏幕密度替代绘制的资源,因为几乎每个应用程序都有一个启动图标,该图标就应该在所有的屏幕密度很好看。同样,如果你在应用程序中其他的位图可绘制资源(如菜单图标,或在应用程序中其他图形) ,您应为不同的密度提供替代版本。

注意:您只需要提供密度相关的可绘制的位图文件(.png ,.JPG或.gif )和九补丁文件( .9.png ) 。如果你使用XML文件来定义形状,颜色,或其他可绘制资源,你应该把一个副本放在默认绘制目录(drawable/ )。

要为不同密度创建替代可绘制的位图,你应该按照3 : 4 : 6 : 8 : 12:16这6种广义密度之间的缩放比例。例如,如果你有一个位图绘制这是48×48像素的中等密度的屏幕,所有不同尺寸应该是:

  • 36x36 (0.75x) for low-density
  • 48x48 (1.0x baseline) for medium-density
  • 72x72 (1.5x) for high-density
  • 96x96 (2.0x) for extra-high-density
  • 180x180 (3.0x) for extra-extra-high-density
  • 192x192 (4.0x) for extra-extra-extra-high-density (launcher icon only; see note above)

图4 不同密度的位图相对大小

有关设计图标的详细信息,请参阅图标设计指南(http://developer.android.com/guide/practices/ui_guidelines/icon_design.html),其中包括各种位图大小信息,如Launcher的图标,菜单图标,状态栏图标,图标标签,以及更多。

声明平板布局(Android 3.2)
对于第一代运行Android 3.0平板电脑,正确的方法来声明平板电脑的布局是把它们放在一个目录为xlarge配置限定符中(例如, res/layout-xlarge / ) 。为了容纳其他类型的平板和屏幕的尺寸,特别是,7“的平板,Android3.2引入了一种新的方式来为多个分立的屏幕尺寸指定资源。这种新技术的基础是空间布局需要的量(如600dp宽度) ,而不是试图让你的布局符合广义尺寸组(如large或xlarge ) 。

当使用广义尺寸组为7寸平板进行设计时非常棘手,因为7寸平板在技术上与5寸的手持设备是属于同一组(large)。而且这两种设备大小也彼此接近,但用于应用程序UI的空间量和用户交互方式明显不同。所以7寸平板和5寸手持设备屏幕不应该总是使用相同的布局。为了让你可以为这两组类型的屏幕提供不同的布局,Android现在允许你根据宽度或者高度指定你的资源来适配你的实际应用布局,指定dp为单位

例如,在你为平板样式的设备设计好布局之后,你也许才确定这个布局在小于600dp的宽度屏幕上无法运行良好。这个门槛也隐藏成为你需要为你的平板电脑布局的最小尺寸。因此,你现在可以指定只有至少有600dp的宽度时这些布局可以为你的应用程序UI使用。

所有你应该选择一个宽度设计作为你的最小尺寸,或者测试什么是你布局支持的最宽度。

注意:请记住,所有这些新的API的单位都使用屏幕无关像素(dp)以及布局方面也始终使用dp单位定义,因为你在乎的只是屏幕的可用空间(相对于使用原始像素分辨率)。

使用新的大小限定符
不同的资源配置,你可以指定表2中基于可用的布局空间的限定符,这些新的限定符将为你提供更多的控制特定屏幕尺寸应用程序支持,相比于传统屏幕尺寸组(小,正常,大,以及超大)

注意:你指定使用的这些限定词的大学不是实际屏幕的尺寸。相反,这些尺寸是以dp为单位的宽或者高提供给你的activity窗口使用。Android系统也许使用一些作为系统UI(比如屏幕顶部的状态栏或者底部的系统栏),所以一些屏幕不能为你的布局所用。因此,你声明的大小应该是你的activity所需要的。同时要注意,操作栏被认为是应用程序窗口的一部分,尽管你的布局不声明它,但是其减少了可用的空间布局,你必须在设计中考虑它。

表2:关于屏幕大小的新配置限定符(Android 3.2)







虽然使用这些限定词似乎比使用屏幕尺寸组更加复杂,但实际上应该更简单,一旦你确定了你的UI需求。在你设计UI的时候,你可能更关心在实际尺寸下使用哪种风格界面,是平板式的多个窗格,还是手机的单窗格样式。
这种转换的确切点取决你的设计,也许你需要一个720dp宽度的平板电脑布局,也许600dp就够了,或者480dp。或者他们之间的一些数字。使用以上的限定词,你用精确的尺寸来控制布局的变化。

配置实例
为了帮你设计适合不同类型设备的屏幕,这里有一些典型的屏幕宽度

  • 320dp: 一款典型的手机屏幕 (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
  • 480dp: 一般的平板 (480x800 mdpi).
  • 600dp: 7” 平板 (600x1024 mdpi).
  • 720dp: 10” 平板 (720x1280 mdpi, 800x1280 mdpi, etc).
使用表2的新限定符,你的应用程序可以在手机和平板电脑之间切换使用不同的布局资源,如果600dp是平板电脑布局支持的最小可用宽度,你可以提供两套布局:

res/layout/main_activity.xml           # 对手机
res/layout-sw600dp/main_activity.xml   # 对平板
在这种情况下,对于使用平板布局所需的最小宽度必须是600dp。

对于要进一步定制UI的大小,如7 “和10”平板电脑情况下,你可以附加定义最小宽度布局:

res/layout/main_activity.xml           # For handsets (smaller than 600dp available width)
res/layout-sw600dp/main_activity.xml   # For 7” tablets (600dp wide and bigger)
res/layout-sw720dp/main_activity.xml   # For 10” tablets (720dp wide and bigger)
注意,以上两套资源示例使用的都是“最小宽度”限定符, sw <N >dp ,其中规定了两个方向的最小屏幕,无论设备当前处在什么方位。因此,使用sw<N >dp是忽略屏幕的方向指定整体屏幕尺寸可供布局的简单方法。

如果你关注屏幕的可用高度,那么你可以使用h<N>dp限定符来做,或者你需要更加的具体化屏幕的方向,同时使用w<N>dp和 h<N>dp 两个限定符。

声明屏幕尺寸的支持
一旦你实现了支持不同屏幕尺寸的布局,在manifest文件中声明你应用支持的屏幕尺寸也是一样重要
随着新的配置限定符选项,Android3.2推出<supports-screens>的manifest新元素属性。

指定所需的最小的宽度。smallestWidth是提供给你应用程序用户界面的屏幕空间的最小尺寸(以dp为单位),也就是说,在两个维度上的最短可用屏幕。所以,为了使一个设备被认为是应用程序兼容的,该设备的smallestWidth必须等于或者大于改值。(通常情况下,无论屏幕的当前方向,你的布局支持的这个最小宽度这个值)
例如,如果你的应用仅适用于具有600dp最小宽度可用平板式设备:

然而,如果你的应用所安装的所有屏幕尺寸都小于426dp x 320dp,那么你并不需要声明这个属性,因为你应用程序所需要的最小宽度不可能在任何设备上。

此属性允许你使用指定最大的“最小宽度”,使你的应用程序支持的屏幕兼容模式为用户可选功能。如果设备的可用屏幕最小边大于这个值,用户仍然可以安装应用程序,但是在提供的屏幕兼容模式运行它。默认情况下,屏幕的兼容模式被禁止。你的布局像往常一样调整大小以适应屏幕,在系统栏的按钮可以允许用户切换屏幕兼容模式的开关。
注意:如果你的应用程序的布局大小能够适应大屏幕,我们建议你避免使用这个属性,而是确保你按文档为大屏幕构建布局

这个属性可以让你指定最大的“最小宽度”,你的应用程序支持强制启用兼容模式(注意,这是以上一个属性的区别,上一个用户选项,这里是强制)。如果设备的可用屏幕的最小边大于你的这里的值,应用程序没有办法为用户禁用这个兼容模式。
注意:如果你的应用程序的布局能够适应大屏幕,我们不建议你使用这个属性。

注意:在开发针对Android3.2以及更高版本时,你不应该使用上面列出的属性组合,同时使用新属性和旧的屏幕尺寸属性可能会导致意外的行为。


最佳实践
支持多屏的目标是创建一个能够正常运行,并能在任何Android支持的屏幕配置上好看的应用程序。本文档的前面几节提供了有关Android如何适应你的应用程序的屏幕设置,以及如何自定义不同的屏幕配置的应用程序外观信息。本节提供一些额外的技巧和技术,帮助你的应用程序适应不同的屏幕配置。

这里是确保你的应用程序在不同屏幕上快速正确显示的清单:
  • 在XML布局文件中指导尺寸时,使用wrap_content,fill_parent或者dp单位
  • 不要在你的应用程序代码中使用硬编码的像素值
  • 不要使用AbsoluteLayout(不建议使用)
  • 提供备用的位图来绘制不同屏幕密度的图像

以下为更详细的说明

1.使用WRAP_CONTENT , FILL_PARENT或DP单元布局尺寸
当定义XML文件属性android:layout_width 和 android:layout_height时,使用"wrap_content"和"fill_parent"或者dp单位的值,确保视图在目前设备上有一个适合的尺寸

例如,对于一个layout_width=“100dp”的图,在中密度屏幕上占据100像素宽度而在高密度屏幕上扩展到150个像素,以使图在屏幕上占据大致相同的物理空间

同样的,你应该使用sp来定义文字的大小,这个sp比例因子依赖于用户设定,系统将扩展它为dp大小。


2、不要在你的应用程序代码中使用硬编码的像素值

出于性能的考虑,并为了保持代码简单,Android系统使用像素值作为表达维度或者座标的标准单位。这意味着,一个视图的尺寸在代码中始终是用像素表示的,但这是根据当前屏幕的像素密度。例如,如果myView.getWidth()返回是10,那么认为是在当前屏幕上的10个像素,如果在具有较高密度屏幕的设备上,这个返回值可能是15。如果你应用程序代码使用像素值来处理没有缩放适配当前屏幕的位图,那么你可能需要在代码中缩放位图资源的像素值来适配当前屏幕。


3、不要使用AbsoluteLayout

不像其他的窗口布局小部件,AbsoluteLayout强制使用固定的位置来布置其子视图,这很容易导致用户界面在不同的屏幕上无法很好工作,因此AbsoluteLayout在Android1.5(API 3)已经过时。

你应该使用RelativeLayout,它对子视图使用相对的位置,例如你可以指定一个按钮控件出现在一个文本小部件的右边(“to the right of”)


4、使用大小和密度特定的资源

虽然系统可以根据当前屏幕配置的绘制资源扩展你的布局。但你仍然要为不同的屏幕尺寸的用户界面,提供不同密度优化的位图资源。这基本上是重申了本文档早期的信息

如果你需要精确的控制你的应用程序在不同屏幕配置的布局,调整特定资源目录中的布局和位图,例如,假设你要显示中,高密度的屏幕图标,简单的创建两个不同大小的图标(例如100x100中密度和150x150高密度),并放在适当的目录中,使用适当的限定符:

res/drawable-mdpi/icon.png   //for medium-density screens
res/drawable-hdpi/icon.png   //for high-density screens
注意:如果在目录名中没有定义密度限定符,那么系统将假定该目录中的资源是为中密度基线所准备的并会将其扩展以适应其他的密度


附加的密度注意事项

本节将介绍更多关于Android系统如何在不同屏幕上扩展位图资源和你如何在不同的像素密度上更进一步的控制位图的绘制。本节的信息,对于大多数应用程序不是非常重要,除非你在不同屏幕密度下运行或者你的应用程序在操作图形的时候遇到问题。

为了更好的理解怎么能够在运行操作图形时支持多种密度,你应该明白系统如何通过以下方式确保位图适当的伸缩

1、预缩放资源(比如位图资源)

基于当前的屏幕密度,系统使用你应用程序的任何大小或者特定密度的资源不进行缩放的显示它们。如果资源在当前密度不可用时,系统会加载默认资源并且根据匹配当前密度的需求适当缩放它们。系统假设默认资源(没有配置限定符文件夹下的)是专为基准屏幕像素密度而准备,除非他们从有特定密度相关的资源目录下加载。预缩放就是系统重新调整位图的大小从而适应当前的屏幕。

如果你请求预缩放资源的尺寸,系统会返回缩放后的尺寸值。例如,在mdpi上设计的一个50x50do的位图在hdpi的屏幕上会被缩放到75x75dp(如果没有应用与hdpi的备选资源)

有些情况下,你可能不希望Android预缩放资源。避免预缩放资源的方法很简单,就是创建使用nodpi为限定符的资源目录,如下所示

res/drawable-nodpi/icon.png
当系统使用该目录下的位图时,系统不会基于当前屏幕像素密度缩放它。

2、自动缩放尺寸和座标

应用可以在manifest文件中设置android:anyDensity="false"来禁止使用预缩放,或者编码设置位图资源的属性“isScaled”禁用预缩放。在这种情况下,系统在绘图时会自动缩放任意绝对像素座标和像素尺寸值。这样做是为了确保像素定义的屏幕元素显示合适的物理尺寸。系统为应用程序透明的处理这个缩放并且报告缩放的像素尺寸给应用程序,而不是物理像素尺寸。

例如,假如一台设备具有一个480x480dp的WVGA高密度屏幕同时尺寸和传统的HVGA屏幕相同。运行的应用程序禁止了预缩放功能,在这种情况下,当查询屏幕尺寸的时候系统会依据应用,并报告320x533(近似mdpi的屏幕密度),当应用程序进行绘制操作的时候,比如画一个从(10,10)到(100,100)的长方形时,系统会根据合适的量缩放座标,可能实际画的区域是从(15,15)到(150,150)。如果你的应用程序直接操作缩放位图,这种差异可能导致意外的行为。但是为了保持应用程序更好的表现,这被认为是一个合理的权衡。

通常情况下,你不应该禁用预缩放。支持多屏的最好方法是遵循上诉的基本技术。


如果你的应用程序操作位图或者以其他的方式与屏幕上的像素直接进行交互,你可能需要采取更多的措施来支持不同屏幕密度。例如,如果你通过手势计算手指穿过的像素数量,你需要使用密度独立的虚拟像素而不是实际像素值。


运行时缩放位图对象

如果你的应用程序创建了一个内存中的位图(一个bitmap对象)时,系统假设这个位图是为中密度的屏幕设计的。默认情况下,绘制的时候自动缩放这个位图。当位图没有特殊的密度特性时,系统对位图提供自动缩放。当你没有正确考虑设备的屏幕密度和指定位图的密度特性,自动缩放可能导致不好的效果当你不提供可替代的资源。

要控制运行时创建的位图是否缩放, 你可以使用setDensity()函数指定位图的密度,从DisplayMetrics传递一个密度,比如DENSITY_HIGH或DENSITY_LOW

如果你使用BitmapFactory(比如文件或者流)来创建位图,你可以使用BitmapFactory.Options来定义位图的属性,这可以确定是否和如何让系统缩放它。例如,你可以使用inDensity字段来位图的密度是否被设计和inScaled字段来指定位图是否应该缩放以匹配当前设备的屏幕密度。

如果你设置inScaled字段是false,那么你禁用任何缩放,系统将会自动缩放,使用自动缩放比预缩放可能更耗CPU,但使用较少内存。

图5:预缩放和自动缩放的位图比较



图5表明在高密度屏幕上加载低(120dp),中(160dp),高(240dp)密度的位图时预缩放和自动缩放的结果,差异是微小的,因为所有的位图都被缩放以匹配的当前的屏幕密度,但是略有不同的外观,这取决于是否是预缩放或者自动缩放的。

注意: 在Android3.0及以上,由于图形框架的改善,预缩放和自动缩放位图之间没有明显差异。


转化dp单位到px单位

在某些情况下,你将需要的dp尺寸转化为像素尺寸。想象一个滚动或者手势滑动应用,用户手指必须移动至少16个像素才能被识别,在基准屏幕上,一个用户必须移动16px/160dpi,等于1/10英寸(2.5毫米)才会被识别。而在一个高密度设备上(240dpi),用户只需要移动16px/240dpi,相当于1/15英寸(1.7毫米)就可以被识别,移动距离更短,应用程序应该对用户手势表现的更敏感。

要解决这个问题,手势识别必须使用dp单位,然后再转化为实际的像素,例如:

// The gesture threshold expressed in dp
private static final float GESTURE_THRESHOLD_DP = 16.0f;

// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);

// Use mGestureThreshold as a distance in pixels...
根据当前屏幕密度,你必须指定DisplayMetrics.density字段作为dp单位转化为px单位的比例因子。在中等密度的屏幕,DisplayMetrics.density等于1.0;高密度等于1.5;超高密度的比例因子为2.0;在低密度时,它等于0.75.你的当前dp值必须成语这个数字才能得到当前屏幕的实际像素值(添加0.5f然后将其转换为最接近的整数)。有关的详细信息,请参阅DisplayMetrics这个类。


使用预缩放的配置值

你可以使用ViewConfiguration这个类去访问通常的距离,速度和Android系统的时间。例如,框架所使用的滚动阈值的像素距离可以用getScaledTouchSlop()函数获得:

private static final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();

如何测试你的应用在多个屏幕上的表现
在发布你的应用程序之前,你应该彻底在它所有支持的屏幕密度和尺寸的设备上测试。Android SDK中包含了你可以使用的模拟器,它是复制了常见的密度和尺寸大小的仿真样式机,你也可以调整模拟器的尺寸和密度。所以你可以通过使用模拟器而不必为了你的应用程序屏幕支持而购买各种设备。

图6:一套为测试屏幕支持的模拟机


要创建测试你的应用程序的屏幕支持的环境,你必须创建一系列模拟机(Android虚拟设备)。模仿出你喜欢你的应用程序支持的屏幕大小和密度。要做到这点,你可以使用AVD管理器创建他们。

为运行Android SDK管理器,打开你Android SDK目录下的执行文件manage.exe(仅在Windows上),或者从<sdk>/tools/directory(所有平台)执行android。图6显示了AVD管理一系列的AVDs

表3显示了Android SDK显示的各种仿真机型,你可以用它来模拟一些常见的屏幕配置。

有关创建和使用AVD来测试您的应用程序,更多信息请看http://developer.android.com/tools/devices/managing-avds.html

表3:Android SDK中各种屏幕配置模拟器



我们还建议你设置紧密匹配你实际设备物理尺寸的模拟器来运行你的程序,这让它的测试结果更加可靠。为了做到这点,你必须知道你的电脑显示器的大致的密度(dpi),比如,一个30“戴尔显示器拥有96dpi的密度。当你从AVD管理器启动一个AVD,你可以指定模拟机的屏幕,并启动显示器DPI选项,如图7


图7:启动AVD时设置大小和密度


当你的想测试的屏幕尺寸或者密度内置的机型不支持,你可以创建一个自定义分辨率或者密度的AVD,当你从AVD管理器中创建AVD时候,指定而不是选择一个分辨率(或者密度)。


如果你用命令行启动AVD,你可以使用-scale选项来指定模拟器的scale。例如:

emulator -avd <avd_name> -scale 96dpi

有关通过命令行创建AVD的更多信息,请参阅http://developer.android.com/tools/devices/managing-avds-cmdline.html


OVER

啃下来真是累。。。废话太多准备总结一下出点干货

还有英文有限,翻译的不好的地方请大家指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章