Android 适配不同分辨率屏幕

来源:互联网 发布:php字符串转换成数组 编辑:程序博客网 时间:2024/05/15 10:18

为了查看方便,特意贴一段 Google API 文档:http://developer.Android.com/intl/zh-cn/guide/practices/screens_support.html



近期做些关于手机适配的工作。

下面来总结一下,希望可以对大家有帮助,本人能力有限,如果有解释失误的地方,请务必帮忙指出,谢谢。


首先引入几个概念。


PPI : Pixels Per Inch的缩写简称,表示的是每英寸显示屏所拥有的像素(pixel)数目。

DPI : Dots Per Inch , 最初用于衡量打印物上每英寸的点数密度,就是说你的打印机可以在一英寸内打多少个点。

DPI用来表示输出设备的输出精度,如打印机,显示器

DPI表示的是 像点/英寸(每英寸长度上有多少个打印点或像点)

PPI用来表示输入设备的输入精度,如扫描仪,数码相机

PPI表示的是 像素/英寸(每英寸长度上有多少个像素)


显然,在谈到Android设备屏幕时,用DPI 比较合适,官方文档中也是用DPI来说明的。当然,如果有人说成PPI,也并不妨碍理解,只是这种说法不太准确。

关于如何计算DPI ,下面我们拿三星S3为例。

根据三星官网给的 信息:

The S III's HD Super AMOLED display measures 4.8 inches (120 mm) on the diagonal. With a 720×1280-pixel (720p) resolution, its pixel per inch (PPI, a measure of pixel density) is a relatively high 306。

我们可知:分辨率为 720x1280(高宽比为16:9) , 4.8英寸 , 306dpi。

那么,这个dpi是如何计算出来的呢?


由于对角线长为4.8英寸,我们要计算对角线上一共有多少像素点。

勾股定理可知:斜对角线的像素点 =   


进而求每英寸的像素点个数,即 (在Android中,大家把PPI 和 DPI 看成一个东西即可)

这么计算后可知,三星S3的DPI = 306. 即,该手机每英寸有306个像素点。


下面再介绍Android中非常重要的几个概念。

dp (或 dip) , Density-Independent Pixels. 按照字面意思:密度无关的像素点。

那么,何为Density?

先了解一下屏幕的级别:

屏幕级别

屏幕密度DPI

密度比值

像素量/英寸

通常的分辨率

ldpi

120

0.75

120

 240x400

mdpi

160

1

160

320x480

hdpi

240

1.5

240

480x800

xhdpi

320

2

320


xxhdpi

480

3

480


在这里,Android将mdpi 下 px:dp = 1:1换算。将其设置为baseline后,它的density为1.其他手机的density就能轻易算出来。

(可能有人会问为何dp是这么定义的?因为,Android历史第一部手机:T-mobile G1 就是这种分辨率)

(出自HTC,2010年停产,里程碑产品)

如果不是以上给出的这些通常的分辨率,那么我们如何确定它的DPI呢?

比如手机基伍A800 ,5.0英寸 , 分辨率为540x960 , 根据公式计算得出 DPI = 220,

那么,就近原则,它的屏幕密度被认为是240dpi , density = 1.5 , 找的相关资源图片在 drawable/hdpi 文件夹下。

如果想利用sw<N>dp来进行进一步的适配。那么,sw<N>dp 中的N如何计算?

Step1:
可以通过adb命令来快速获取手机的屏幕参数:
adb shell dumpsys window displays
(this command can get all display information, include resolution and dpi.)
通过该命令,我们可以取得手机的dpi(dot per inch),以及分辨率等。

Step2:
dp和px的换算公式: dp = (px * 160)/ dpi


注:这里的dpi是归化后的dpi,并非是真实的dpi。基伍A800的真实dpi为220dpi,归化后的dpi只有这几种:

  • A set of six generalized densities:
    • ldpi (low) ~120dpi
    • mdpi (medium) ~160dpi
    • hdpi (high) ~240dpi
    • xhdpi (extra-high) ~320dpi
    • xxhdpi (extra-extra-high) ~480dpi
    • xxxhdpi (extra-extra-extra-high) ~640dpi

Android会取就近的dpi值,220离240最近,所以基伍A800的机器dpi为240.

拿A800 为例,屏幕分辨率为 960*540 ,dpi 为 240。
因为我们要计算sw<N>dp的N ,sw(smallest-width),即最小可用宽度。
所以该N的计算的公式: dp = (540*160)/ 240 = 360.
如果为480*800 、 480*854   dp = 480*160 / 240 = 320.
所以,A800在适配的时候,找到的dimen.xml是Res/values-sw360dp/dimen.xml

补充说明:
Android在适配的时候会找小于等于N的资源。
比如A800,其smallestWidth的N=360.如果你不是将资源放在Res/values-sw360dp/dimen.xml中,
而是放在Res/values-sw340dp/dimen.xml中。也不影响它正确适配。只是不够精确罢了。

如果某款手机的smallestWidth的N=300 ,都适配不到的情况下,Android将默认去res/values/dimen.xml中寻找。
为了防止crush,请在默认的dimen.xml中也配置上相应参数。

2015-06-25 再次补充:

在机型适配的时候,还会碰到更加棘手的问题。
比如:
三星S2的分辨率:480*800
小黄蜂hyf9300的分辨率:480*854
此时,小黄蜂的分辨率在竖直方向的高度比S2多了54像素点高度,而上述的sw<N>dp仅仅是针对smallestWidth的情况。
两款手机的sw均为320dp,不能很好的区分两款手机。此时该如何做呢?

谷歌在3.2以后推荐使用以下这几种方法来进行适配:

Table 2. New configuration qualifiers for screen size (introduced in Android 3.2).


其中,h<N>dp是在该情况下可以用到的。但是,该处的N和sw<N>dp中的N有区别。
根据英文描述我们可以知道,此处的N和手机的orientation有关。
横竖屏切换时,N也随着变动,并且N值是指的是UI可用高度。这个地方的可用高度不包含systemUI占用的高度,诸如状态栏等。
也就是说,当你计算出竖直方向的高度后,还要减去系统UI所占用的高度(包括状态栏和titlebar等)。
除非你的应用已经设定orientation是固定的,这样你才可以放心地使用该方法来处理机型适配问题。

了解了上面的知识后,我们开始为下面3款机型适配。(下面所说的h<N>dp都是android:screenOrientation="portrait"的情况下

机型

分辨率

全屏高度h<N>dp

三星S2

480*800

N = 800*160/240 = 533.33dp

小黄蜂

480*854

N = 854*160/240 = 569.33dp

A800

540*960

N = 800*160/240 = 640dp

由于我们团队开发的应用只有状态栏是属于systemUI,所以该N还得减去状态栏的高度为25dp。

机型

分辨率

可用高度h<N>dp

三星S2

480*800

N = 533.33 - 25 = 508.33dp

小黄蜂

480*854

N = 569.33 - 25 = 544.33dp

A800

540*960

N = 640 - 25 = 615 dp

该h<N>dp的适配逻辑和sw<N>dp一样。

比如小黄蜂手机打开的应用检测出其可用高度为544.33dp,

先查找对应的文件夹即:values-h544.33dp/dimen.xml,如果没有找到,那么向下匹配。

实在找不到,最后才去values/dimen.xml中默认匹配。

所以,最后在保证可以查找到并且允许状态栏等高度小幅度变化的情况下,我们在代码中设定其高度为:

机型

分辨率

h<N>dp

对应的适配文件

三星S2

480*800

N = 500dp

values-h500dp/dimen.xml

小黄蜂

480*854

N = 540dp

values-h540dp/dimen.xml

A800

540*960

N = 610dp

values-h610dp/dimen.xml

当然,最后还是别忘了在values/dimen.xml文件中加入默认的配置,以防在找不到的情况下发生crush。

0 0
原创粉丝点击