关于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|举报|字号 订阅 项目需要,需要对中英文字符串进行遍历修改等, ...
随机推荐
- [MEF] 学习之一 入门级的简单Demo
MEF 的精髓在于插件式开发,方便扩展. 我学东西,习惯性的先搞的最简单的Demo出来,看看有没有好玩的东东,然后继续深入.这个博文,不谈大道理,看demo说事儿. 至于概念,请google ,大把大 ...
- hd acm1008
Problem Description The highest building in our city has only one elevator. A request list is made u ...
- ansible普通用户su切换问题
在现网应用中,安全加固后的主机是不允许直接以root用户登陆的,而很多命令又需要root用户来执行,在不改造现网的情况下.希望通过一个普通用户先登陆,再su切到root执行.而且每台主机的普通用户和r ...
- poj3301 Texas Trip【三分算法】
题目地址:http://poj.org/problem?id=3301 简述:T组测试数据,每组线输入n,代表有n个点,接下来输入这n个点的坐标,坐标都是整数. 要求用一个最小的正方形覆盖所有的点,输 ...
- ML一(概念学习和一般到特殊序)
概念学习和一般到特殊序 Concept Learning and the General-To-Specific Ordering 1 简介 1.1 定义 概念学习(Concept Learning) ...
- POJ 1639 Picnic Planning:最小度限制生成树
题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...
- Android之史上最全最简单最有用的第三方开源库收集整理
Android开源库 自己一直很喜欢Android开发,就如博客签名一样, 我是程序猿,我为自己代言 . 在摸索过程中,GitHub上搜集了很多很棒的Android第三方库,推荐给在苦苦寻找的开发者, ...
- POJ1060 Modular multiplication of polynomials解题报告 (2011-12-09 20:27:53)
Modular multiplication of polynomials Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3 ...
- 大数据日志分析产品——SaaS Cloud, e.g. Papertrail, Loggly, Sumo Logic;Open Source Frameworks, e.g. ELK stack, Graylog;Enterprise Products, e.g. TIBCO LogLogic, IBM QRadar, Splunk
Learn how you can maximize big data in the cloud with Apache Hadoop. Download this eBook now. Brough ...
- js 定义hash类
// JavaScript Documentfunction HashTable(){ this._hash={}; this._count=0; /** *添 ...