第一部分:开发前的准备-第四章 多分辨率多屏幕的支持

第4章 多屏幕多分辨率的支持

若是你买过Android手机的话,销售员通常会向你推荐这个android手机是最新版的系统啦,屏幕有多大,分辨率是多少之类的。这只是外表上的多屏幕和多分辨率,其实android内在还有一些影响因素,例如“密度”的概念。本章为详细的为你解释一些基础概念并适当的举一些例子教你怎么处理关于多屏幕多分辨率的支持。 虽然Android系统内置有一些机制能使用多屏幕多分辨率,但咱们仍是应该在加点外力来更加优化用户体验的效果。android

4.1多屏幕支持概述

4.1.1基本术语和概念浏览器

屏幕大小eclipse

根据屏幕对角线实际测量的物理大小(android已经根据屏幕大小分为四类small, normal, large, extra large)工具

屏幕密度布局

屏幕物理区域一个单位(通常用英寸)的像素数量,通常简称dpi(‘dots per inch’每英寸中包含的点的数量,记住DPI这个概念很重要)学习

这里android也分为四类 low, medium, high, extra high.测试

方向优化

从用户的角度看设备只有两个方向,那就是横屏和竖屏。关于横竖屏最好也要出一套相对应的UI,由于长宽比不同,特别是对于软件项目通常都是出两套(游戏通常都会锁定一个方向)。编码

分辨率spa

一个物理屏幕上像素点的总数。通常咱们的应用不会直接使用分辨率,而是使用密度和屏幕大小(但某些特殊状况下,能够指定分辨率)

独立密度像素(Density-independent pixel ‘dip’)

一个虚拟的单位,用来定义UI布局的。它是表述布局的尺寸大小或者位置。

dip(注 意dip是独立像素单位,dpi是屏幕密度)等价于一个160dpi(medium密度)的屏幕,运行时系统会根据你实际屏幕的密度来自动处理缩放。像素和dip 的转换公式为px =dp*(dpi/160) 。例如在240密度的屏幕上一个dp等于1.5个像素(dp=px*1.5)。之后咱们应该尽可能使用dip单位布局,不要使用像素单位。这样会使你的应用屏幕兼容性更好。最后咱们应该区分dpi和dip它们一个字母的不一样表明的意思就不同。之后程序中咱们通常使用dp来代替dip用来描述位置和尺寸大小,而dpi则是屏幕密度,这里你们须要稍微留心一下。下面咱们来举个游戏的例子:

关于android多屏幕多分辨率这道门槛,咱们能够把它当作一个boss,要打败这个boss咱们须要了解它的5个弱点(也能够理解成游戏套路)

  1. 屏幕大小---boss的体型,boss都有体型之分的,例如WOW中的BOSS大部分都是巨型,而有些游戏中的boss比较小,例如剑网3的boss就比较小。
  2. 屏幕密度---boss的模型细粒度,有些boss你能看清它的每一个外观细节,但有些boss就比较模糊,虽然你的电脑显卡或者游戏模型的材质会影响外观细节。但请忽略它们!
  3. 方向---这个要以咱们的角度来观察boss才能得出结论,例如你靠近boss并站在高处和你远离boss站在低处看boss彻底是两个感受。
  4. 分辨率---这个能够理解为对boss整体的外观和风格,它是由boss的体型和boss的模型细粒度加在一块儿体现出的一种外观和风格,因此说分辨率咱们通常是经过密度和屏幕大小来匹配。
  5. dip---boss的伤害公式,boss的伤害实际上是一个数字,但这个数字是有公式转换的,例如法系攻击,物理攻击的都是有一个公式转换后在附加到咱们身上。固然请不要纠结你的防护,抗性之类的,dip就是一种转换公式,让不一样的boss都能统一转换成正确的伤害。

4.1.2多屏幕支持的范围

Android1.6开始就支持多屏幕和密度了,这都是为了更好的用户体验,为了简化咱们多屏幕的开发。android提供了一组范围让咱们使用:

关于屏幕大小: small, normal, large, xlarge(看来目前游戏boss的体型就这四种)

注意: android3.2会有些不一样,之后咱们在讲平板和手机支持时会说明

屏幕密度: ldpi (low), mdpi (medium), hdpi (high), xhdpi (extra high) (boss的模型细粒度目前也就四种了)。这些广义的大小和密度都是基于normal大小和mdpi来当作标准的。通常来讲咱们分辨率为800*480或者854*480的手机密度都是240(hdpi),屏幕大小都为large。

每个大小和密度都有一个跨越幅度。但这些幅度中具体的微调咱们是不用关心的,android会帮咱们处理,下面咱们来看图 4-1:

 

 图4-1 实际大小和实际密度的取值范围(这是个近似值)

 

咱们设计UI都会要考虑一个最小化的空间,android中都是使用dp(dip)单位的。如下是官方参考

xlarge 屏幕至少960dp x 720dp

large 屏幕至少 640dp x 480dp

normal 屏幕至少 470dp x 320dp

small 屏幕至少 426dp x 320dp

屏幕大小和密度是能够独立的,不是说一个5寸屏的密度就必定是hdpi。有一个很重要的例子就是例如一个WVGA (800×480)屏幕可能在不一样的设备上会有mdpi和hdpid两种密度。也就是说一样体型的boss,有的模型很粗糙,有的很细腻。

 

4.1.3独立密度

独立密度是很重要的,由于没有它,一个UI元素(好比一个按钮)会出如今一个物理屏幕很大,但密度不多的显示效果(看起来就是像是被强行放大的,失真很严重)。这样相对位置的改变会出问题,下面咱们来看图:

 

 图4-2 你的应用没有支持不一样密度产生的效果

 

图4-3你的应用具备良好的支持而产生的效果

android 系统帮助你的应用实现独立密度的方法有两种:

1.系统缩放dp单位来适用当前屏幕密度

2.系统基于当前屏幕密度缩放drawable资源到适用的大小

图 4-2是用像素单位来定义的大小。你发现他们的布局彻底变了,有的大有的小。这是由于他们的实际屏幕大小多是同样的,高密度屏幕每英寸的像素更多(因此你会发现像素同样,但高密度的设备显示出来的效果却很小)。图4-2使用的是dp单位,基于mdpi密度的设备它不会变化,ldpi它会自动缩小,hdpi它会自动放大。因此效果很是好。图片显示出来的样子和大小彻底同样。

使用密度系统会缩放图片使之看上去彻底同样,但细心的你会发现有些图片变模糊了。因此咱们应该提供可选择的图片资源让系统来自动选择图片以适应不一样的密度。因此用Eclipse自动生成的工程项目中的hdpi,mdpi,ldpi三个文件夹就是用在这里的。这样就不会有模糊的感受了。固然对于矢量图来讲放大的失真也没什么影响,这里能够理解为只针对位图。

4.2怎样支持多屏幕

以上咱们学习了这么多的理论基础。如今咱们应该优雅的处理它们了。

1. 明确的在manifest文件中指出你的应用支持的屏幕大小。

咱们能够有选择性的过滤掉一些老掉牙的设备,以减轻咱们的工做量。但这并非一个好的方法仅供参考。在manifest 中使用节点<supports-screens>

2. 根据不一样的屏幕大小提供不一样的布局

默认的android会调整你应用的布局来适应当前设备的屏幕。大多数状况下能够知足,但某些特殊状况,你的UI可能须要一个更精确的调整。例如,一个larger 屏幕,你可能想要利用额外的屏幕空间调整位置和一些元素的大小,或者一个小屏幕中,你可能须要调整到恰好合适。好比你须要适应一个extra large 屏幕。你能够在文件夹layout-xlarge/下放置布局(读者请记住通常layut下放的都是xml布局文件)。

Android 3.2开始,有一种新的方式。例如你的平板需求至少600dp的屏幕宽度,你可使用layout-sw600dp 这种文件夹放置你的布局文件。之后咱们在平板一节会详细描述。

3. 根据不一样的屏幕密度提供不一样的位图

默认android会缩放你的位图(.png.jpg.gif),另外还有一种专用的Nine-Patch(.9.png)。例如,你的应用提供的位图仅仅为标准密度(mdpi),那么在hdpi的屏幕上这些位置会被等比放大。因此咱们应该有选择性的对于不一样的屏幕密度包含不一样的分辨率。

因此android针对图片资源配置后缀,前面咱们知道的4种密度(ldpi,mdpi,hdpi,xhpi),若是用于高密度的屏幕,咱们应该使用drawable- hdpi/这种文件夹。以上关于屏幕大小和密度的后缀都符合屏幕支持的那些范围。

在运行时, 对于给定的资源系统会使用如下这些步骤来显示:

1. 系统会使用合适的替代资源

基于当前屏幕的大小和密度,系统会针对屏幕的密度和大小使用资源。例如,若是设备有一个 hdpi的屏幕那么当App请求一个drawable 资源时,系统会在最匹配的的设备配置下的drawable 资源目录寻找。能够取决于其余可替代的资源,使用drawable-hdpi/的资源目录最匹配的,因此系统会使用drawable-hdpi目录下的资源。

2. 若是没有可用的匹配资源,系统会使用默认资源等比放大或缩小以匹配当前屏幕的大小和密度。

这里的默认资源是没有后缀的。例如,“drawable”就是默认的drawable/ 资源。系统会认为默认的资源都是基于normal 屏幕大小和medium 密度设计的。系统会等比缩放默认的密度资源来匹配hdpi密度或者ldpi密度。当系统没有找到针对密度资源的目录时,它就一直会使用默认的资源。例如,若是系统想找一个ldpi(低密度)的资源,但找不到。那么系统会等比缩小hdpi的资源,为何不寻找mdpi呢?由于系统对于hdpi更容易缩放,它的系数为0.5,相比mdpi的0.75来讲。0.5的的性价比更高(方便计算,正确率也高一点)。关于这一点最好的证实就是android版本的QQ浏览器。你解压后发现它关于drawable就只有drawable和drawable-hdpi两个文件夹,看来腾讯里android的开发者应该很熟悉android系统规律了,由于默认的drawable 就是mdpi,只须要定义一套hdpi的drawable资源就好了。

4.2.1使用配置后缀

Android支持几种配置后缀,它容许你控制系统有选择性的筛选基于当前屏幕设备的资源文件。一个配置后缀就是一个String你能够在资源目录文件夹下追加指定的后缀便可。使用一个配置后缀的方法步骤:

1.在你的工程res/目录下建立一个新的目录,格式为<资源名>-<后缀>: 

<资源名>是标准的资源名字(例如 drawable或者layout)

<后缀> 是指定屏幕配置使用哪种资源(例如hdpi或者xlarge)

咱们可使用的后缀不只仅只有一个哦,在一个文件夹下咱们能够同时使用多种后缀来限定资源,使用"-"便可。

2.在新的目录中保存合适资源,资源文件的命名必须和默认资源文件同样。

例如 xlarge是一个后缀用于extra large 屏幕。当你追加后缀时(例如layout-xlarge) ,它说明系统会在extra large屏幕上使用这些资源

屏幕特征

后缀

描述

大小

small

资源用于small大小的屏幕.

normal

资源用于normal 大小的屏幕。(这是默认的基准大小)

large

资源用于large 大小的屏幕

xlarge

资源用于extra large 大小的屏幕

密度

ldpi

资源用于 low-density (ldpi) 密度的屏幕 (~120dpi).

mdpi

资源用于medium-density (mdpi) 密度的屏幕 (~160dpi).

(这是默认的基准密度.)

hdpi

资源用于high-density (hdpi) 密度的屏幕 (~240dpi).

xhdpi

资源用于extra high-density (xhdpi) 密度的屏幕 (~320dpi).

nodpi

资源用于全部密度. 系统不会根据当前屏幕密度去缩放资源

tvdpi

资源用于mdpi 和hdpi二者之间的某的密度;大约是213dpi。

这个不多用到。它主要用于电视,大多数App不须要用到它。

若是你须要tvdpi资源,它的大小大概是1.33*mdpi(160)例如,

一个在mdpi下100px*100px的图片,那么在 tvdpi中它会

变成133px*133px。的图片,那么在 tvdpi中它会变成133px*133px。

方向

land

资源用于横屏

port

资源用于竖屏

长宽比

long

资源用于长宽比相差很远的配置(相对于4寸(normal)屏幕左右基准屏幕)

notlong

资源用于长宽比差很少的配置(相对论,同上)

表格4-1 后缀配置表

注意: 若是对于android3.2或者更高的版本,有一些新的后缀,等下咱们会讲解

下面咱们就来举一些详细的例子:

res/layout/my_layout.xml             // 用于normal 屏幕大小的布局 ("默认")
res/layout-small/my_layout.xml       // 用于small 屏幕大小的布局
res/layout-large/my_layout.xml       // 用于large屏幕大小的布局
res/layout-xlarge/my_layout.xml      // 用于extra large屏幕大小的布局
res/layout-xlarge-land/my_layout.xml // 于extra large屏幕大小而且是横屏的布局

res/drawable-mdpi/my_icon.png        // 用于中等密度的位图
res/drawable-hdpi/my_icon.png        // 用于高密度的位图
res/drawable-xhdpi/my_icon.png       // 用于超高密度的位图

当android系统在运行时选择资源时,当你没有加后缀时它本身有必定的逻辑判断来匹配最适合的资源。当基于使用大小的后缀时,若是当前没有资源更好的匹配你的后缀,那么系统会使用比当前屏幕更小的资源来计算(例如,若是你没有添加large后缀,那么一个large大小的屏幕将会使用在normal(默认的)大小的屏幕资源来放大后显示),若是可用的资源后缀比当前屏幕更大(其实仍是没匹配上),那么系统将不使用它们(例如你吧全部layout资源放入xlarge后缀中,但设备是一个normal屏幕,系统就不会使用这些资源)。

是否是有点头晕了,简要的概述下就是若是没有匹配的系统会使用默认的资源,若是连默认下都没有放资源而且没有匹配到你的后缀,那么系统就没有资源可用啦。

注意:某些状况下你可能须要用到nodpi后缀,由于你可能不想要它被缩放,或者你想要在运行时经过代码手动缩放它。 

4.2.2设计可供选择的Layouts和drawables

咱们应该根据于本身应用程序的需求来建立可供选择的资源类型。一般,你应该使用大小和方向后缀来提供可选择的Layout资源,使用密度后缀来提供可选择的位图drawable资源

可供选择的layouts

你应该知道你的应用是否有这个需求,是否须要根据不一样的屏幕来提供可选择的布局。例如:

1.当在一个small屏幕上测试时,你发现你的布局没有彻底符合你的要求或者是没有匹配好屏幕。例如一排按钮没有很好的在small屏幕上显示。这种状况你应该为small屏幕提供一个可供选择的布局用来调整按钮的大小或者位置。

2.当在一个extra large屏幕测试时, 若是没有有效利用大屏幕或者明显的被拉伸了,这种状况你也应该提供一种根据extra large屏幕的布局,而且最好再优化它以适应未来的平板设备

虽然你的App没有提供大屏幕的布局运行起来也没问题,但UI被明显拉伸的感受会让用户以为这个应用不太精致,用户体验会大打折扣

3.当在横屏和竖屏对比测试时, 你应该注意到UI元素在竖屏下是在底部,横屏下倒是右边。若是你一直须要都在底部的话,你也应该配置后缀

总的来讲,你应该确保你的应用布局以下:

(1)适用于小屏幕

(2)优化应用程序使之在大屏幕上利用额外的空间

(3)优化横竖屏

若是你的UI使用位图,那么你应该使用nine-patch 位图文件。nine-patch 这是android提供的一种格式而且它还提供一种根据让你吧美工出的图片稍微修饰。这种格式能容许你设置能够缩放的2D范围。当系统须要缩放时,系统会在你指定区域缩放 Nine-Patch位图。这样在不一样的屏幕大小下你就不须要提供不一样的位图资源了(能够节省APK的大小)。由于Nine-Patch会自动调整它的。但在不一样的屏幕密度下你应该仍是提供可供选择的Nine-Patch 文件。这样你的应用才会更健壮。关于nine-patch的使用咱们之后会在第二大篇的图形章详细讲述。

可供选择的drawables

几乎每个应用都会根据不一样的密度提供可选择的drawable资源,由于这对于用户体验和UI真的很重要。下面咱们来看一下图4-4的密度转换图

 

图4-4 根据每个密度下drawable下位图的相对大小(目前4种技能应该够用了)

注意: 根据密度你仅须要提供drawable下的位图文件,若是你使用Xml来定义shape,colors或者其余drawable的资源,你就应该放到"drawable/"默认目录下

根据不一样的密度提供可选择的位图drawable资源时,你应该在四种密度下使用3:4:6:8的缩放比。读者能够参考工程下每一个不一样的drawable里的icon尺寸:

36x36 ldpi

48x48 mdpi

72x72 hdpi

96x96 xhdpi

 

4.3关于Android3.2平板上的布局

第一代平板运行于android3.0上,通常是使用xlarge配置后缀(res/layout-xlarge/)来声明平板布局。为了提供其余类型的平板和屏幕大小----尤为是7寸平板!android3.2引入了一种新的方法来为更多离散的屏幕大小来指定资源。你的布局须要一种新的基于控件容量的技术(例如指定600dp的宽度),而不是试图使你的布局去适应那些android归纳性的分组(例如large或xlarge)

当android去归纳大小分组时,对于7寸平板他们也很棘手,由于5寸手机和7寸平板使用一样的large组。这两个设备在size上表面上看起来更贴近彼此,但其实UI在至关大程度上仍是不一样的,用户体验的效果也不太好。所以一个7寸和5寸的屏幕将不使用一样的layout。根据这两种屏幕你应该尽量的提供不一样的布局,android如今容许咱们指定基于宽度或高度layout资源,记住请使用dp单位。

例如, 在你根据平板风格设计布局之后,你可能须要当屏幕小于600dp的宽度时候中止工做。这个界限会由于你的平板布局而变成最小的尺寸。这样你能马上指定当至少宽度在600dp时候,layout中的资源文件才被用到。

注意: 记住!dip是一个很是重要的单位,你的布局大小也应该用dp单位。由于它能够看作一种比例单位而非像素那样的绝对单位。

4.3.1使用新的大小后缀(非密度)

你能为你的布局指定不一样的资源配置。在下方的表格2中这些新的后缀提供给你更多的控制,相对于传统的(small, normal, large, and xlarge)这些已经超过它们了

注意: 你指定使用的这些后缀并不是实际的屏幕大小。固然,这些大小是根据宽度(dp单位)和高度(dp单位)被用于activity的window中。window的特殊性在于它方法是有个动做条,用来显示电池和通知信息的。因此你在设计UI的时候须要考虑 你的应用是否须要显示动做条。下面咱们看下面表格4-2:

屏幕 配置

后缀值

描述

最小宽度

sw<N>dp

例如:
sw600dp
sw720dp

用这个后缀能够确保无论当前屏幕是否横竖屏。你的应用有一个至少<N>dp的可用宽度 

例如, 若是你的layout一直需求最小屏幕的一边为600dp,那么你能使用这个后缀建立layout资源(res/layout-sw600dp/)。对于用户来说,无论600dp是宽仍是高,仅当屏幕可用的最小尺寸至少是600dp时,系统会使用这些资源(就是说你的设备不用以什么角度看,长和宽的某一边的最小值大于或等于600dp时,系统就会使用)。当屏幕水平方向改变时,设备的最小宽度不会改变

设备的最小宽度要考虑屏幕的装饰和系统UI。例如,若是设备有一些持续不变的沿着你最小宽度的轴方向的UI元素(动做条等),那么系统会宣布最小宽度比实际屏幕宽度要小,由于那些UI元素对于你的UI来讲是不可用的

 由于宽度是常常影响布局的一个重要因素,因此使用最小宽度来控制通常的屏幕大小(针对平板)仍是有用的。 可用宽度也是决定是否使用单屏幕布局(手机)和多屏幕布局(平板)关键因素,所以你极可能关心每个设备上的最小方面。

屏幕可用宽度

w<N>dp

例如:
w720dp
w1024dp

用dp单位指定一个最小化的在可用宽度下可使用的资源。系统会根据宽度改变(横竖屏切换时)来匹配这个值,并反映到当前实际可用的宽度上

当你决定是否使用多屏幕布局时它颇有用,由于即便在平板设备上,你也常常不想要多屏幕布局会根据横竖屏来变化。所以你能够用这个来指定最小化的宽度需求,它能够用来代替方向后缀(land,port)和大小后缀(small,normal,large,xlarge)使之整合到一块儿。

屏幕可用高度

h<N>dp

例如:
h720dp
h1024dp
etc.

用dp单位指定一个最小化的屏幕高度。和"屏幕可用宽度"相似

表格4-2 android3.2加入的新后缀(注意是基于屏幕大小的而不是密度)

当使用这些后缀时你可能以为比传统的那四种后缀复杂些,实际上你用事后就发现它很简单,它能一次简化你的UI需求。当你设计UI时,主要的事情就是须要考虑咱们App中的实际大小,而且对于手机和平板风格的切换。它取决于你某些特定切换点的设计,可能对于平板布局你须要720dp的宽度,可能600dp就足够了,或者480,或者这两个之间。使用表格2的后缀,你能够在布局改变时精确的控制大小。之后咱们会根据实际开发来说述的

4.3.2关于实际配置的例子(非密度)

如下是一些屏幕数据:

320dp: 一种手机屏幕(240x320 ldpi, 320x480 mdpi, 480x800 hdpi, 等).

480dp: 一种平板 (480x800 mdpi).

600dp:  7寸平板(600x1024 mdpi).

720dp: 10寸平板(720x1280 mdpi, 800x1280 mdpi, 等).

咱们使用表格2中的后缀来为咱们的应用定义不一样的切换风格(包括手机和平板),例如, 若是咱们的平板布局600dp是最小可用宽度,咱们能提供两套布局方式:

res/layout/main_activity.xml           # 手机
res/layout-sw600dp/main_activity.xml   # 平板

这种状况下,屏幕可用的最小宽度为600dp,这是伪了支持平板布局被应用。

或者你可能想要区分7寸和10寸平板,你能够这么作:

res/layout/main_activity.xml           # 手机(比600dp更小的可用宽度)
res/layout-sw600dp/main_activity.xml   # 7寸平板 (600dp的宽度或者更大)
res/layout-sw720dp/main_activity.xml   # 10寸平板(720dp的宽度或者更大)

注意上面的两套例子的使用使用 sw(最小宽度)后缀,它指定屏幕的两边中的最小一边,无论屏幕的水平方向。它忽视横竖屏。

然而某些状况下咱们须要精确布局。例如若是你有一个 2个面板合并在一块儿的显示效果。是否屏幕提供至少600dp的宽度,是否横竖屏你都要使用它。就应该这:

res/layout/main_activity.xml         # 手机(小于600dp的可用宽度)
res/layout-w600dp/main_activity.xml  #多面板 (任意一个面板都是600dp或者更高的宽度)

注意上面这里用的是w<n>dp。实际设备可能须要两套布局,它依赖于屏幕的水平方向(一边至少是600dp的宽度,另外一边小于600dp,你会发现无论横竖屏都知足这个条件。因此你须要准备两套关于横竖屏的布局)

关于什么是多屏手机或者叫多面板手机。我发个图给你们看看就明白了(下面这个手机其实有3屏),如图4-5所示:

 

图4-5 三屏手机截图

4.4实践中应该注意哪些

在多样的屏幕中咱们使用传统的四种配置仍是能很好的得到支持的。上面咱们提供了多种定义的方法。添加这些后缀能确保你的App能适应不一样的屏幕设备。下面是一些方法,告诉你如何确保你的应用程序能够正确地显示在不一样的屏幕上:

1.在XML布局文件中请使用wrap_content, fill_parent, 或者 dp 单位

2.在你的程序代码中最好不要使用像素(px)这种硬编码

3.不要使用AbsoluteLayout (绝对布局)

4.提供不一样的位图drawable资源来适应不一样的屏幕密度.

1. 使用在XML布局文件中请使用wrap_content, fill_parent, 或者 dp 单位

当在XML中为你的Views定义android:layout_width和android:layout_width时,使用"wrap_content","fill_parent"或者dp单位来保证View在当前屏幕上得到一个合适的大小。

例如,一个view的宽为layout_width="100dp"   在mdpi的屏幕下它是100px,在hdpi的屏幕下它就是150px,但显示出来的效果在物理屏幕上是同样的大小

一样, 对于定义文本的大小,咱们应该用sp(scale-independent pixel)。 由于sp和dp的概念是同样的,它们不是绝对的像素值

2.在你的程序代码中最好不要使用像素(px)这种硬编码

因为执行缘由并使代码更简单,android系统使用像素做为标准单位用来描述尺寸或坐标值。就是说在代码中android仍是使用的像素用来表述尺寸,但它是基于当前屏幕密度的,因此是变化的。若是代码中 View.getWidth()返回的值是10,这么这个10的单位为像素,但这仅仅是在某一个密度的屏幕上而已,其余不一样密度的屏幕上它的结果就会不同了。因此android是不建议咱们在代码中用像素来设置布局的,由于它会加剧咱们的工做量,而且处理的也不必定很好。想象一下这么多屏幕设备你若是用代码来适配的话,你就得考虑的很是严谨了。不过若是你只针对某一种屏幕的话就另当别论了,但这种状况不多见。

3.不要使用AbsoluteLayout (绝对布局)

请不要使用AbsoluteLayout(绝对布局)这种布局是早期android的版本,在android1.5版本的时候就已经废弃了。虽然为了兼容之前很老的设备这种布局还存在,但目前来讲,咱们已经彻底没有必要再使用它了。 

4.提供不一样的位图drawable资源来适应不一样的屏幕密度

虽然在当前屏幕配置上系统会自动缩放你的layout和drawable资源,但为了优化某些特定密度的设备,可能咱们并不想让它缩放,咱们想给这种密度指定一套资源也是能够并且这样的效果也很不错,能更好的根据不一样的屏幕来调整咱们的UI。这个咱们在本文中已经反复提到了,目的就是为了加深你的印象。

一个很好的例子就是关于你用eclipse生成android工程的时候,三种不一样的drawable(res/drawable-ldpi/icon.png,res/drawable-mdpi/icon.png,res/drawable-hdpi/icon.png)中都

会自动生成不一样尺寸的icon.png。

注意: 若是咱们没有定义某个后缀,但屏幕密度又是须要那个后缀的话,那么系统会假定你的资源都是基于mdpi(默认)的。并会放缩你的资源

4.5 关于密度额外的注意事项

这一段主要描述android在不一样屏幕密度上是怎么缩放位图drawable的,咱们须要更进一步的掌握系统控制位图资源的原理。当在运行时操做图形,咱们能更好的理解它是怎样支持多屏幕的,咱们应该了解下系统是如何保证适应屏幕并适当的缩放位图的:

1.载入时自动缩放 (好比位图drawables)。

基于当前屏幕的密度,系统使用任意大小或者密度的资源来显示它们的时候是没有缩放过的。若是在当前密度下没有可用的资源,那么系统会载入默认资源并等比缩放它们来匹配当前屏幕的密度。除非有有针对密度的后缀出现,否则系统都是认为默认资源(没有后缀的drawable)是为mdpi的密度来设计的。所以系统这个时候会调整位图的大小来适应屏幕。

若是你需求资源缩放以前的大小,那系统实际上返回的是缩放后的大小。例如:若是你没有指定hdpi后缀,一个在mdpi下50px*50px的位图在一个hdpi下会缩放为75px*75px。在hdpi屏幕下系统会返回这个75px这个大小。若是你不但愿系统根据不一样的密度来缩放资源,那么请记住使用“res/drawable-nodpi/”

2.运行时自动缩放(好比像素的大小和坐标)

一个应用能关闭载入时自动缩放的这个功能,只要你在manifest中设置android:anyDensity ="false",或者在程序中使用BitmapFactory.Options.inScaled返回的值为false。在这种状况下。系统会在绘制的时候自动等比缩听任何绝对坐标和像素大小。这么作确保用针对像素的屏幕元素能一直显示。系统会处理缩放,而后转化并报告缩放的像素大小,而不是物理像素大小。下面咱们来举个例子:例如,假设一个设备有一个WVGA(800*480)下是hdpi的屏幕,而且它和在传统的HVGA(480*320)屏幕同样的物理大小,但执行应用的时候关闭了载入时自动缩放这个功能。这样的话,当系统查询屏幕大小时,它会报告一个320*533的大小,为何会是320*533呢,咱们开的模拟器是800*480的啊!!由于系统在绘制的时候缩放了。系统报告的是缩放后的像素大小,而不是咱们模拟器上的物理大小。而后App须要绘制操做时,原本想在(10,10)上的位置绘制,但会变成(15,15)。若是你的应用直接操做缩放位图,那这种差别可能致使意外的行为。之前不少刚开始接触android的朋友常常会遇到系统报告320*533的这种问题。缘由就是因为咱们关闭了载入时自动缩放这个功能。你关闭了它的话,它就会在运行时缩放并返回结果。因此咱们要检查manifest中是否设置android:anyDensity ="false"。若是有赶快去掉。也许还有朋友发现没有设置怎么也会出现这种问题,这是因为之前比较老的SDK版本系统默认设置关闭了载入时自动缩放这个功能致使的,不过目前这种状况不多发生了。 

4.5.1运行时建立缩放的位图对象

咱们的应用若是须要在内存中建立一个位图(bitmap)对象,那么系统会认为你是基于mdpi密度的屏幕来建立的。默认的,系统会根据屏幕密度在绘制的时候自动缩放这个位图。当位图没有指定密度属性时候,系统会自动缩放。为了控制位图在运行时建立后是否被缩放,咱们能够指定位图的密度属性,使用Bitmap.setDensity()。具体的值能够传DisplayMetrics.DENSITY_HIGH或其余。咱们还能够从文件或者一个流中使用BitmapFactory来建立位图,使用BitmapFactory.Options来定义位图的属性,那么系统会根据你的属性来缩放它。咱们还可使用BitmapFactory.Options.inDensity来指定这个位图是否须要匹配当前的屏幕密度。若是咱们设置BitmapFactory.Options.inDensity=false;那么系统在载入位图时将不会自动缩放它,只会在运行时缩放它。使用运行时缩放CPU占用率高,内存占用低。使用载入时缩放CPU占用率低,内存占用高。如何取舍就看你的需求了。

4.5.2 dp和像素的转换

有些状况下,dp和px只须要相互转换的。例如一个应用在用手指滑动屏幕的时候会感应用户的手指移动了多少个像素。在一个normal和mdpi的屏幕下,用户必须移动16px/160dpi,等价于十分之一英寸(大约2.5mm(毫米))。那么在一个hdpi(240dpi)的屏幕上用户必须移动16px/20dpi,等价十五分之一英寸(1.7mm)。距离是很短的,所以这对用来讲会很敏感。为了修复这个问题,须要用代码吧dp转换成px单位。例如:

 

// 手势的响应的范围(dp)

privatestaticfinalfloat GESTURE_THRESHOLD_DP =16.0f// 获取屏幕的密度来缩放

finalfloat scale =getResources().getDisplayMetrics().density;

//根据密度吧dp转换成px

mGestureThreshold =(int)(GESTURE_THRESHOLD_DP * scale +0.5f);

// 可使用这个响应的范围了

 

 

这里DisplayMetrics.density的值为(0.75[ldpi],1[mdpi],1.5[hdpi],2[xhdpi]) ,其实咱们还可使用ViewConfiguration类来处理,但前提是打开了载入时缩放这个功能(目前来讲,默认都

是开的不用担忧)而且咱们可使用ViewConfiguration.getScaledTouchSlop()来直接得到换算距离。具体使用以下:

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

 

4.6 如何在多种屏幕下测试咱们的应用

首先咱们来看一下图4-6,这是使用AVD工具设置虚拟设备的截图

 

图4-6 这是android SDK中的AVD工具,它提供一套虚拟机设备。(最后1,2章会详细讲述使用方法)

在发布咱们的应用以前,我应该在不一样的屏幕大小和密度上测试咱们的App。android SDK中有不少模拟器,咱们能够修改模拟器上的默认的大小,密度,分辨率来整合测试。例如使用android2.1版本的模拟器,咱们能够同时新建多个2.1的版本,但每一个的密度不一样。这么多模拟器能够为咱们省下不少钱来买不一样的手机。若是你想修改某个模拟器的密度,你只须要选中它点击右边的edit就能够修改了。以下图4-7所示:(这里只须要留点印象后面会有章节单独的讲述AVD参数配置)

 

图4-7 在AVD中点击edit后的截图

为了测试应用是否支持多种不一样的屏幕,咱们应该建立一系列的AVD(android virtual devices)。若是不用eclipse的话,咱们能够在sdk目录下执行SDK Manager.exe这样就显示出图4-6的界面。

4.7 本章小节

关于android的屏幕和分辨率,这是很是重要的一个知识点,但愿你们认真学好它,在之后的开发过程当中绝对是很是有帮助。如今咱们稍微回顾一下关键的内容:

一,Boss的5个关键点

1.boss的体型(屏幕大小)

2.boss的模型细粒度(屏幕密度)

3.咱们看boss的角度(屏幕的方向)

4.boss的整体外观和风格(屏幕的分辨率)

5.boss的伤害公式(dp单位)

二,咱们也有相应的对策对付他们

drawable(咱们游戏角色的技能,目前4种(ldpi,mdpi,hdpi,xhdpi))

layout(咱们游戏角色的装备,目前4种(small,normal,large,extra large))

三,怎么样搞定这些boss

manifest文件中指出你的App支持的屏幕大小

根据不一样的屏幕大小提供不一样的布局

根据不一样的屏幕密度提供不一样的位图

四,最后咱们须要熟悉后缀和一些公式(就像游戏boss的攻略)

目前那么多后缀不须要彻底记住(之后用的多天然就记住了),但须要有个印象(后缀能够为drawable服务,也能够为layout服务,你能够想象成后缀是一种附魔提高装备(layout)的属性,又是一种铭文用来提升技能(drawable)伤害或效果)

还记得3:4:6:8吗? 还记得 0.75x, x ,1.5x, 2x吗?这些都很重要哦

本文来自jy02432443,QQ78117253。转载请保留出处,并保留追究法律责任的权利

相关文章
相关标签/搜索