Screen的这些基本概念中,最重要的就是dip的理解,而理解dip就是理解android适配不同设备的关键。

Screen Size

实际物理尺寸。就是我们常说的3.5英寸屏幕,4.7英寸屏幕等等,这个长度说的是对角线的长度。在android中屏幕物理尺寸划分为这么几类:small,normal,large,extra large。下面是对尺寸以及密度的一个粗略分类。该图可能会由于实际设备尺寸和屏幕密度的不断增加而更新,最新的请到官网查看。

图1

Resolution

“屏幕”分辨率,即屏幕上的像素总数。常用的表现形式如:1280x720, 1920x1080等。

Screen density

屏幕密度,与dpi表达的同一个意思,两种不同的描述方式。官网如是说:

Screen density

  • The quantity of pixels within a physical area of the screen; usually referred to as dpi (dots per inch). For example, a "low" density screen has fewer pixels within a given physical area, compared to a "normal" or "high" density screen.

public floatdensityThe logical density of the display.

public intdensityDpiThe screen density expressed as dots-per-inch.

但其实我的理解他就是一个缩放系数,具体原因在后面解释。按照屏幕密度所有的手机可被划分为以下几类:ldpi (low,低密度), mdpi (medium,标准密度), hdpi (high,高密度), and xhdpi (extra high,超大密度)。

DPI(dot per inch)

每英寸像素数。与density描述的都是屏幕的密度。但请注意这个翻译,实际上应该译为每英寸点数。为说明原因,不得不引入另一个概念:PPI(Pixel per inch),每英寸像素数。实际PPI用于电脑显示领域,DPI用于打印或印刷领域,但从很久之前两个概念就已经开始混用:

“点”有时用来表示像素,特别是计算机市场,由于计算机显示器如LCD或CRT是由一个个极小的点来描绘图像的,LCD显示器在标准屏幕分辨率下,对于一个像素可认为是由显示器的一个“点”来显示,因此ppi有时所写为DPI(dots per inch,每英寸点数)——维基百科:像素

到android这里,干脆就用dpi取代ppi代表像素密度。

DPI计算方法

像素密度=屏幕总像素数/屏幕大小。通常我们知道屏幕的尺寸是诸如3.5英寸,5.0英寸等,这是对角线长度,我们可以先获取对角线上的总像素数,再除以对角线长即可。

拿Mi2s举例说明:4.3英寸,1280x720。对角线上像素值根据勾股定理可得√(1280^2+720^2)≈1468.6,接着1468.6/4.3≈341.5

然而,从代码测试的结果看起来是有偏差的:

Density:2.0

DensityDpi:320

Resolution:1280x720

xDpi:345.0566 // x方向上(宽)每英寸像素数

yDpi:342.23157 // y方向上(高)每英寸像素数

可以看出,xDpi≈yDpi≈341,与我们的计算结果相近。但DensityDpi是320,为什么呢?在Screen Density中已经说过,android将所有屏幕的实际密度归类,处在某个区间内的密度是个定值,参考下表:

密度分类 DPI值(像素/英寸) Density值
ldpi 120 0.75
mdpi 160 1
hdpi 240 1.5
xhdpi 320 2
xxhdpi 480 3

表1

根据图1种的分类,Mi2s的真实dpi为341,341>300,所以Mi2s属于xhdpi,再结合表1,得出DensityDpi=320。

从上面的数据也可以看出Density和DensityDpi值不同,但规律是显而易见的。在android中,mdpi是标准值,android将其density定为1,以此为准得出Density与DensityDpi的关系是:dpi=density*160。

我的疑问是,既然dpi可以代表屏幕密度,还要density干什么?想要搞清楚该死的density,必须要结合dp,往下看。

Density-independent pixel (dip,或dp)

独立像素,虚拟单位,又称设备无关像素。1dp的长度相当于一个160dpi的屏幕上一个物理像素的长度。而160dpi的屏幕则是被android定义为基准的屏幕(mdpi)。在app运行的时候,android会将dp转为实际像素进行布局。转换的公式为:px = dp * (dpi / 160)

为什么要dip

设想app将一张图以像素为单位进行布局,该图为400px的正方形图,当app运行在1920x1080上时看起来比较小,运行在960x640上时显得非常的大,而我们想要看到的效果是app运行在两个手机上时这张图看起来是大小相近的效果。

看下面这张图是以px为单位进行布局的效果:

图2

下面这张图是使用dp布局的效果:

图3

想要达到这样的效果,就需要在高密度手机上对其进行放大操作,低密度手机上对其进行缩小操作。但是我们无法预期自己的app会安装在什么密度,什么尺寸的手机上,即使知道也不可能为每个手机准备一套图,因此希望android能智能一些,我设置一个大概的尺寸,android能自动适配不同手机。于是就有了独立像素这个单位。见名之意,开发人员只需要用dp或者直接使用wrap_content,剩下的交给android,系统会为你的布局和图片做缩放。

dp怎么来的

那么,android是如何创造出这个独立像素的?

首先,我们的思路是从原来用px进行布局,改为用dp布局,由于最终dp还是要转化为px,引入一个系数λ,则有:px=dp*λ,λ就是我们的缩放系数;

其次,我最终目标是让所有手机上看到的图大小相同,那么到底多大,是不是要有个标准,我就选一个定做标准,让其他不同密度的手机显示的跟这个标准一样大。那么我把这个标准就定为160像素/英寸吧,取个名字叫mdpi,接着把其他密度的手机进行分类:ldpi(120像素/英寸),hdpi(240像素/英寸),xhdpi(320像素/英寸);

再次,归类都归好了,下面就开始缩放吧:

当app运行在标准手机上(mdpi),图片应该不缩放,因为它是标准,即λ=1,此时px=dp;

当app运行在ldpi手机上时,由于密度小于标准,图像的长更长,宽更宽,为了保持与标准相同的长宽,在ldpi上长要缩小原来的120/160=0.75,宽亦如此,即λ=0.75,此时px=0.75*dp;

当app运行在hdpi上时,λ=1.5,px=1.5*dp;

以此类推。。。

由上面的推导,其实λ=dpi/160=density,可见density就是λ

结论

1. 从官网的概念得知density与dpi都是描述屏幕密度的,似乎是相同的概念,但何必用两个同名概念来描述让人混淆呢?我个人觉得何不把他们从命名上做个区分,density就是个缩放系数,dpi才是对密度的准确描述。因此我只用dpi来表示屏幕密度,或像素密度,而density其实就是缩放系数,或密度系数;

2. 即使在某一个密度分组区间内(比如xhdpi)不同的密度的手机所展示的同样大小的图片,仔细看也不会完全相同,毕竟他们的密度不同。因此android只是尽最大可能简化适配的工作,分组并不能百分百解决适配的问题。

SP

专用于android中的字体大小。sp产生的初衷与dp是相同的,只是它应用于字体大小。

那些恶心人的Screen基本概念的更多相关文章

  1. Android核心分析 之二方法论探讨之概念空间篇

    方法论探讨之概念空间篇 我们潜意识就不想用计算机的方式来思考问题,我们有自己的思维描述方式,越是接近我们思维描述方式,我们越容易接受和使用.各种计算机语言,建模工具,不外乎就是建立一个更接近人的思维方 ...

  2. oracle实例名,数据库名,服务名等概念差别与联系

    数据库名.实例名.数据库域名.全局数据库名.服务名 这是几个令非常多刚開始学习的人easy混淆的概念.相信非常多刚開始学习的人都与我一样被标题上这些个概念搞得一头雾水.我们如今就来把它们弄个明确. 一 ...

  3. 《人月神话》读书笔记(2)-week3

    为了确保团队中的每个人都能保持系统概念上的完整性,关于项目的书面规格说明是必不可少的.手册要描绘用户可见的一切,但不应支配实现的过程.光有规格说明也是不够的,会议也是必要的.书中提到的周例会会迅捷地给 ...

  4. 如何卸载烦人的2007组件,windows提供的解决方案

    如何卸载烦人的2007组件:很恶心人各种软件已经手动删除卸载都无法用,不是cd/dvd找不到就是什么msi文件找不到:对于这种恶心的问题,windows提供了如下解决方案:我使用fixit轻松卸载,很 ...

  5. css 选择器三

    2.4.10 浮动 浮动是css里面布局最多的一个属性,也是很重要的一个属性. float:表示浮动的意思.它有四个值. none: 表示不浮动,默认 left: 表示左浮动 right:表示右浮动 ...

  6. Hibernate级联操作 注解

    EJB3 支持的操作类型 /** * Cascade types (can override default EJB3 cascades */ public enum CascadeType { AL ...

  7. 关于Store Apps

    因为时代在变迁,Store Apps这个概念很容易引起混淆 在过去,windows phone 8.0时代 windows store apps指的是windows metro style 的应用, ...

  8. 我的美国(北美)计算机CS实习面试经验分享

    过去的一年多里,参加了一些面试,虽然面过的公司不多,但都从头一直走到尾.毕竟自己也是花了大量的时间和精力在这一场场的面试里.所以,就絮叨下自己的一些经验,希望能给在美国找实习找工作的同学们提供一点点帮 ...

  9. 再谈Hibernate级联删除——JPA下的Hibernate实现一对多级联删除CascadeType.DELETE_ORPHAN

    声明: 1.本文系原创,非抄袭或转载过来的. 2.本文论点都亲手做过实验论证. 3.本文所讲的Hibernate配置都基于注解的方式,hbm语法未提供. 非常多人对持久层概念搞不清JPA.Hibern ...

随机推荐

  1. 卷积交织/解交织C++程序

    交织基数为M,交织深度为I的卷积交织/解交织程序,延时为I*(I-1)*M. #include <iostream> #include <vector> #include &l ...

  2. 2.6 《硬啃设计模式》第8章 复制不是很难 - 原型模式(Prototype Pattern)

    案例: 某即时战略游戏,你训练出来各种很强的战士. 为了增加游戏的可玩性,增加了一种复制魔法.实施该魔法,可以复制任意的战士. 你会怎样考虑这个设计? 在继续阅读之前,请先认真思考并写出你的设计,这样 ...

  3. Gson 使用总结 高级用法

    Gson基本用法 参考:http://www.jianshu.com/p/e740196225a4 Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列 ...

  4. 用js做一个简单的留言板效果

    html部分: 1: <!DOCTYPE> 2: <html lang="zh-en"> 3: <head> 4: <title>j ...

  5. 一步步教你如何在 Visual Studio 2013 上使用 Github

    介绍 我承认越是能将事情变简单的工具我越会更多地使用它.尽管我已经知道了足够的命令来使用Github,但我宁愿它被集成到IDE中.在本教程中,我会告诉你使用Visual Studio 2013如何实现 ...

  6. JavaScript的js文件压缩和格式化工具

    JavaScriptcompressor.com这个网站可是大名鼎鼎啊.以前在找到过压缩 Javascript 代码的程序,一直在用,感觉效果不错.域名是: http://javascriptcomp ...

  7. SQL基础(三):SQL命令

    下面2个表用于实例演示: 1.SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的每个 SELECT 语句必须拥有相同数量的列.列 ...

  8. Golang 中错误与异常需要重新认识

    如何进行错误处理,这是一个Go程序员之间,特别是一些新的Go程序员,会经常讨论的问题.讨论到最后往往由于以下代码的多次出现而变成了抱怨. if err != nil { return err } 我们 ...

  9. XXX全球 IP 地址库

    XXX全球 IP 地址库 Bulgaria 93.123.23.1 93.123.23.2 93.123.23.3 93.123.23.4 93.123.23.5 93.123.23.6 93.123 ...

  10. [Node.js]31. Level 7: Redis coming for Node.js, Simple Redis Commands

    Let's start practicing using the redis key-value store from our node application. First require the  ...