码迷,mamicode.com
首页 > 移动开发 > 详细

关于android上dpi/screen-size的厘清解释

时间:2015-07-08 02:03:12      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:

android定义了四种screen-size:

small

normal

large

xlarge

同时定义了六种dpi级别:

ldpi (low) ~120dpi
mdpi (medium) ~160dpi
hdpi (high) ~240dpi
xhdpi (extra-high) ~320dpi
xxhdpi (extra-extra-high) ~480dpi
xxxhdpi (extra-extra-extra-high) ~640dpi

定义这些级别的目的在于更好地组织资源,以适应不同的设备。参见:http://developer.android.com/guide/practices/screens_support.html#range

系统在运行我们的app时,会自动根据当前设备的级别,来加载合适的资源,而我们就需要为不同级别准备各自的资源,如为大屏幕上提供一个并列放置两个view的layout,而小屏幕上则一次只显示一个view。

要做到这一点,我们必须要知道,给定一个设备,如何判断它是哪个级别的?然后才能有的放矢,把相应的资源放在正确的级别目录中。

 

首先看screen size,这个级别会影响layout模板的选取,即指定一个R.layout.id_XXX时,到底是从res/layout下加载,还是从res/layout-large下加载呢?

先看官方给的图:

技术分享

第一排是关于size的分档,在这里,各个档是有重叠的,也就是一个大概的范围。

但是我们知道,程序运行时的加载逻辑必须是精确的,针对每一个设备必须获得一个确定的值,以判定它是哪个级别,然后才知道要加载哪些资源。

以上图论,如果我们有一个3.3"的手机,那它到底是small还是normal呢?就无法判断了。

所以,必然要有更准确的计算方法,而这个方法就牵扯到dpi了。

 

dpi:dot per inch,就是指每英寸上有多少个像素点,要计算这个值,就要知道它的物理尺寸和物理分辨率(也就是全屏有多少实际像素点,或者就是说能发光的元件)

比如我们建一个虚拟设备来看:

技术分享

它的物理分辨率是720x1280,物理尺寸是4.7"

可能有人疑问,物理尺寸不也是有宽和高吗,怎么才一个值?这个4.7",是对角线的长度。用对角线来做标称,好处是容许更自由的宽高组合吧。

那么要计算这个dpi,按常理就没法算了,因为1个对角线值无法确定惟一的宽高。

但是换一个思路,将面积密度换成线密度,即用对角线上的像素数量来除以对角线长度,其值应该是一致的,所以dpi计算如下:

dpi = sqrt(pixel_width^2+pixel_height^2)/diagonal = sqrt(720^2+1280^2)/4.7 = 312.5

对照上表,可知其dpi级别为xhdpi,与工具界面上显示的一致。

 

知道了dpi,那么图片类资源的加载目录就知道了,此例中就是res/drawable-xhdpi,但是layout类资源又如何呢?

layout的选取标准与图片资源不同,并不以dpi级别为准,而是要看screen size的级别。

上面在讲screen size分类方法时转而插入对dpi解释,正是为了这里能说清其含义。

实际上官方对screen size的分类标准如下:

  • xlarge screens are at least 960dp x 720dp
  • large screens are at least 640dp x 480dp
  • normal screens are at least 470dp x 320dp
  • small screens are at least 426dp x 320dp

这里给出的宽、高值其实并无单独比较意义,最终结果是看它的乘积。

也就是说最小的屏幕要有426*320=136,320个dp,而要想成为一个中等屏幕则至少需要470*320=150,400个dp,列表如下:

smal = 136,320

normal = 150,400

large = 307,200

xlarge = 691,200

现在问题来了,dp又是什么,和dpi什么关系?针对上例这个设备,它又有多少个dp呢?

先回想一下dpi,它本身是一个比率值,说的是每英寸上有多少个像素点,这是刻划设备能力的一种属性。

然而很多时候能力的绝对值对一般人认知理解来说并不直观(虽然这个例子并不合适,dpi还是很直观的),其相对值才更具有意义。

那么选取第一台android设备为基准,它的dpi是160,其它设备的dpi与160相比,得到一个比率值scale,就是该设备的(dp-)scale,

那么设备的dp则定义为:

dpx = pixel_width/scale

dpy = pixel_height/scale

此例中则其 scale=312.5/160=1.95,dpx=720/scale=369.2,dpy=1280/scale=646.4

也就是以dp单位来衡量,此虚拟设备有一个369 x 646的屏幕,现在可以来计算它的screen size级别了:dp = dpx * dpy = 369 * 646 = 238,374

查上表可知介于150,400和307,200之间,所以它的screen size为normal,当加载layout时,优先使用res/layout里的资源(而非small/large/xlarge)。

 

定义和计算过程清楚后,再回头审视一下dp的含义,为什么要通过如此曲折的方式来定义这样一个单位。

1、其实从物理分辨率到dp(也就是screen size),只是转换了一下手段,但目的还是一样:就是要解决“数清楚屏幕上到底有多少个点,然后我们的ui面板要做多少个点”这个问题。

2、为什么不直接用“物理像素”,会有什么问题?因为不同设备物理尺寸与分辨率之比差别很大,比较极端的情形是,两个分辨率相同的设备,尺寸却差一半,比如这两:

技术分享

技术分享

技术分享

如果以物理像素定义一个面板为400*600px大小,也就是全屏一半的样子,在10"的tablet上看起来大小正合适,而在4.7"的手机上,那就是小小的一砣,这一砣的物理占地只有tablet上1/16!

如果tablet上的视觉效果是合理的,那么很难想象肉眼如何适应这1/16的同质元素

但是改用dp为单位来描述,结果会是如何呢?(计算结果可以在这个网页方便获取:https://www.sven.de/dpi/)

对前者,dpi=149.5,scale~=1.0,screen size(dp)=800*1280

对后者,dpi=317.6,scale~=2.0,screen size(dp)=384*640

如果我们需要一个在tablet占地1/4(也就是宽高各1/2)的区域,那么其dp大小应为400*640

现在计算其在phone上的占地,先换算为像素大小,w=400*2.0=800,h=640*2.0=1280

即这是一个800*1280像素的区域,几乎刚好是整个Phone屏幕大小(考虑上面计算scale时的舍入误差)

而这个大小,在物理尺寸上刚好和tablet上的1/4是一样的。

可见,使用dp来描述大小的优势在于:确保了该区域在不同分辨率和物理尺寸的屏幕上,其物理面积是一样大的!

而物理面积,正是肉眼观察舒适度的重要衡量标准——而不仅仅是分辨率,相信大家都有体会,很多高清屏手机虽然足够细腻,但如果用来看电子书其实很废眼,远不如较低分辨率但更大尺寸的平板)

 

现在,dp的含义和好处清楚后,还有最后一个问题:如果真要设计一个面板,到底该给它多少dp呢?dp既是一个虚拟单位,如何直观地以它来估算大小呢?

其实,可以就用dp的来源——第一个android设备的大小作为基准来考虑,它是一个大小为3.2",分辨率为320*480的手机:

技术分享

在它上面,1个dp就是1个像素。所以,要弄多大的界面,就以它为参考咯!

 

关于android上dpi/screen-size的厘清解释

标签:

原文地址:http://www.cnblogs.com/wellbye/p/4628933.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!