关于android上dpi/screen-size的厘清解释
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的厘清解释的更多相关文章
- 二十一、Android上常见度量单位【xdpi、hdpi、mdpi、ldpi】解读
术语和概念 屏幕尺寸 屏幕的物理尺寸,以屏幕的对角线长度作为依据(比如 2.8寸, 3.5寸). 简而言之, Android把所有的屏幕尺寸简化为三大类:大,正常,和小. 程序可以针对这三种尺寸的屏幕 ...
- Android上常见度量单位【xdpi、hdpi、mdpi、ldpi】解读
术语和概念 屏幕尺寸 屏幕的物理尺寸,以屏幕的对角线长度作为依据(比如 2.8寸, 3.5寸). 简而言之, Android把所有的屏幕尺寸简化为三大类:大,正常,和小. 程序可以针对这三种尺 ...
- Android上dip、dp、px、sp等单位说明(转)
dip device independent pixels(设备独立像素). 不同设备不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和QVGA 推荐使用这个,不依赖像素. 在 ...
- Android上dip、dp、px、sp等单位说明
Android上dip.dp.px.sp等单位说明 dip device independent pixels(设备独立像素). 不同设备不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA ...
- 最牛逼android上的图表库MpChart(二) 折线图
最牛逼android上的图表库MpChart二 折线图 MpChart折线图介绍 MpChart折线图实例 MpChart效果 最牛逼android上的图表库MpChart(二) 折线图 最近工作中, ...
- [原] GLES在iOS和Android上的不同
本来GLES提供了与native platform的接口 EGL, 然而iOS没有使用EGL接口, 而是自己搞了一套,叫做EAGL的类似东西, 虽然说大同小异,但是在做跨平台的时候还是很恶心. elg ...
- Android上使用OpenGLES2.0显示YUV数据
在Android上用OpenGLES来显示YUV图像,之所以这样做,是因为: 1.Android本身也不能直接显示YUV图像,YUV转成RGB还是必要的: 2.YUV手动转RGB会占用大量的CPU资源 ...
- 最牛逼android上的图表库MpChart(三) 条形图
最牛逼android上的图表库MpChart三 条形图 BarChart条形图介绍 BarChart条形图实例 BarChart效果 最牛逼android上的图表库MpChart(三) 条形图 最近工 ...
- android上让我放弃使用wstring来操作中英文字符串 转
android上让我放弃使用wstring来操作中英文字符串 2013-08-07 16:37:24| 分类: cocos2d|举报|字号 订阅 项目需要,需要对中英文字符串进行遍历修改等, ...
随机推荐
- poj 1019 Number Sequence 【组合数学+数字x的位宽函数】
题目地址:http://poj.org/problem?id=1019 Number Sequence Time Limit: 1000MS Memory Limit: 10000K Total ...
- java入门了解10
1.IO: 1.File (一)注意: a.可以表示文件或者文件夹(也可称为目录) b.创建的File对象实际上不存在的文件只是代表了一个抽象路径 c.Windows中分隔符'\'('//'也可以); ...
- 算法(Algorithms)第4版 练习 1.3.31
双向链表实现: //1.3.31 package com.qiusongde.linkedlist; public class DoublyLinkedList<Item> { priva ...
- Java JDK环境配置及说明
一.Java程序运行机制 Java语言编写的程序需要经过编译生成与平台无关的字节码(.class文件). 这种字节码必须使用Java解释器(JVM)来解释执行. JVM是可运行Java字节码文件的虚拟 ...
- linux raid技术
一.概念 磁盘阵列(Redundant Arrays of Independent Disks,RAID),有“独立磁盘构成的具有冗余能力的阵列”之意.是为了提高文件在磁盘上的读写速度而研究出来的. ...
- linux 文件存取 软硬联接的区别
一.linux文件存取过程 在linux系统中根目录是自引用的,比如要找 /etc/sysconfig/networkscripts/ifcfg-0文件 先根据根目录/ 的inode号,在inode ...
- 用python实现的抓取腾讯视频所有电影的爬虫
1. [代码]用python实现的抓取腾讯视频所有电影的爬虫 # -*- coding: utf-8 -*-# by awakenjoys. my site: www.dianying.atim ...
- java:Map借口及其子类HashMap五,identityHashMap子类
java:Map借口及其子类HashMap五,identityHashMap子类 了解:identityHashMap子类 一般情况下,标准的Map,是不会有重复的key值得value的,相同的key ...
- jQuery - 获取/设置内容和属性
获得内容 - text().html() 以及 val() 三个简单实用的用于 DOM 操作的 jQuery 方法: text() - 设置或返回所选元素的文本内容 html() - 设置或返回所选元 ...
- 重拾安卓_01_安卓开发环境搭建(eclipse)
一.下载安装Android SDK 1.下载地址 (1)官网(可FQ选择):http://developer.android.com/sdk/index.html (2)不可FQ选择:http://w ...