Android 常用单位dp

160,240,320,480,
TODO: px 像素,dip,dp,dpi,这几个的概念。适配。
1dp = n个像素? = dpi/160 *1dp = 400/160 = 2.5像素。所以一个1dp在不同手机上,显示像素不一样。

1.1 常用单位

px像素:
dp=dip: Density independent pixels ,设备无关像素。
dpi:dots per inch , 直接来说就是一英寸多少个像素点。常见取值 120,160,240。我一般称作像素密度,简称密度.
density : 直接翻译的话貌似叫 密度。常见取值 1.5 , 1.0 。和标准dpi的比例(160px/inc)
分辨率 : 横纵2个方向的像素点的数量,常见取值 480X800 ,320X480
屏幕尺寸: 屏幕对角线的长度。电脑电视同理。
屏幕比例的问题。因为只确定了对角线长,2边长度还不一定。所以有了4:3、16:9这种,这样就可以算出屏幕边长了。

1.2 在android里面,获取一个窗口的metrics

metrics.density; // 就是我们常说的dpi。
metrics.densityDpi; // 其实是 DPI / (160像素/英寸) 后得到的值。
DPI本身的单位也是 像素/英寸,所以density其实是没单位的,他就是一个比例值。
而dpi的单位是 像素/英寸,比较符合物理上面的密度定义,密度不都是单位度量的值么,所以我更喜欢把dpi叫像素密度,简称密度,density还是就叫density。
densityDpi:240; density:1.5
getResources().getDisplayMetrics().densityDpi 就是屏幕密度。
getResources().getDisplayMetrics().density 也可以理解为1dip相当于多少个px啦。
上面的dpi是240,1dp = 1.5px。

drawable目录对应的最大dpi:
ldpi(120 DPI),mdpi(160 DPI),hdpi(240 DPI),xhdpi(320 DPI),xxhdpi(480 DPI),xxxhdpi(640 DPI)
0.75 1 1.5 2 3 4

3/0.75 = 4;

1.3 放在不同drawable文件夹的区别。

配置:模拟器(10801920 xxhdpi=480dpi), 图片(7201280 xxhdpi)
图片放置ldpi(4倍关系): 图片长=720*(16/4)=2880 图片宽 = 1280 *(16/4) = 5120 scale=480/120=4
图片放置mdpi(3倍关系): 图片长 = 720 *(12/4)= 2160 图片宽 = 1280 *(12/4) = 3840 scale=480/160=3
图片放置hdpi(2倍关系): 图片长 = 720 *(8/4)= 1440 图片宽 = 1280 *(8/4) = 2560 scale=480/240=2
图片放置xhdpi(1.5倍关系):图片长 = 720 *(6/4)= 1080 图片宽 = 1280 *(6/4) = 1920 scale=480/320=1.5
图片放置xxhdpi(1倍关系):图片长 = 720 *(4/4)= 720 图片宽 = 1280 *(4/4) = 1280 scale=1 (无倍数关系,不会对图像进行放缩,保持原始大小)
图片放置xxxhdpi(0.75倍关系):图片长 = 720 *(3/4)=540 图片宽 = 1280 *(3/4)= 960 scale=480/640=0.75

nohdpi(无缩放)

drawable和drawable-mdpi是一样的大小,是因为drawable-mdpi是系统默认的像素密度,其他像素密度都以它为基数,
当只在drawable中存在图片时,如果使用该图片,那么将按照drawable-mdpi的放缩比例进行放缩。
例如,当前设备的dpi是480(即xxhdpi),那么对于存放于mdpi目录中的图片会被放大三倍。
对于很多设备,其dpi并不刚好是六种通用密度最大dpi,这种情况下,图片的缩放倍数如何计算呢?
缩放倍数(缩放因子)计算方法:对于任意设备,各drawable-[density]目录下的图片放大倍数的计算公式
公式:【scale = 设备dpi / 图片所在Drawable目录对应最大dpi】。
那么,图片的实现显示尺寸通过图片尺寸乘以缩放倍数就可以得到了。

1.4 单位间转换

  • 计算dpi

比如一个机器,屏幕4寸,分辨率480X800,他的dpi能算么。
dpi = 开根号(480480+800800)/4。
  因为不知道边长,肯定不能分开算,4是对角线长度,那直接用勾股定理算对角线像素,除以4,算出来大概是 dpi = 233 像素/英寸。
  那么density就是 (233 px/inch)/(160 px/inch)=1.46 左右, density 是没有单位的。
  顺带说下,android默认的只有3个dpi,low、medium和high,对应 120、160、240.
  其中的default就是160。

  • 计算 dp 与 px

我们写布局的时候,肯定还是要知道1个dp到底有多少px的。
  换算公式如下: dp = (DPI/(160像素/英寸))px = density px
  注意,这里都是带单位的。px是单位,dp是单位,density没单位。
  为了方便,假设dpi是240 像素/英寸 , 那么density就是1.5
  那么就是 dp=1.5px ,注意这是带了单位的,也就是 设备无关像素 = density 像素
  那么转换为数值计算的话,应该是下面这个式子
  PX = density * DP
也就是
  像素值 = density * 设备无关像素值 ,请注意这里有个值字。

  • 为啥 标准dpi = 160
    (1)Android Design [1] 里把主流设备的 dpi 归成了四个档次,120 dpi、160 dpi、240 dpi、320 dpi
      实际开发当中,我们经常需要对这几个尺寸进行相互转换(比如先在某个分辨率下完成设计,然后缩放到其他尺寸微调后输出),
    一般按照 dpi 之间的比例即 2:1.5:1:0.75 来给界面中的元素来进行尺寸定义。
      也就是说如果以 160 dpi 作为基准的话,只要尺寸的 DP 是 4的公倍数,XHDPI 下乘以 2,HDPI 下乘以 1.5,LDPI 下乘以 0.75 即可满足所有尺寸下都是整数 pixel。
      但假设以 240 dpi 作为标准,那需要 DP 是 3 的公倍数, xhdpi下乘以 1.333,mdpi下乘以 0.666 ldpi 下除以 2
      而以 LDPI 和 XHDPI 为基准就更复杂了,所以选择 160 dpi.
    (2)这个在Google的官方文档中有给出了解释,因为第一款Android设备(HTC的T-Mobile G1)是属于160dpi的。

  • 屏幕尺寸:屏幕的对角线长度,一般讲的大小单位都是英寸。
    比如iPhone5S的屏幕尺寸是4英寸。Samsung Note3是5.7英寸。

  • 像素:屏幕上每个小点。

  • 分辨率Resolution:屏幕上垂直方向和水平方向上的像素个数。
    比如iPhone5S的分辨率是1136640;Samsung Note3的分辨率是19201080;

  • dpi(dot per inch): 每英寸的像素数,也叫做屏幕密度。这个值越大,屏幕就越清晰。
    比如iPhone5S的dpi是326; Samsung Note3 的dpi是386。

  • dip(Density independent pixel): 指的是抽象意义上的像素。跟设备的屏幕密度有关系。是Android里的一个单位,dip和dp是一样的。

就是说在160dpi的屏幕上,1dip=1px。
  它跟屏幕密度有关,如果屏幕密度大,1dip代表的px就多,比如在320dpi的屏幕上,1dip=2px。

  • 为什么我们在布局的时候最好要用dip,不要用px?

在着很多不同屏幕密度的手机,屏幕密度是什么?就是dpi,就是单位长度里的像素数量。
如果这些手机的尺寸一样,屏幕密度相差很大,那么是不是说一个手机水平方向上像素很少,另一个手机水平方向上像素很多?
那我们画同样pix数量的时候,它显示的长度不就会不一样了?

两种概念:

  • 图片和手机配置都固定的情况下 图片放置到不同文件夹(上面介绍的这种);
  • 图片放置固定文件夹 多分辨率的手机加载(常用场景);
    简述第2中概念:假如 图片固定放到xxhdp文件夹下
    1、你的手机分辨率是1920 * 1080那么图片保持原始大小加载;
    2、手机分辨率是大于1920 * 1080,则会将图片等比放大 加载;
    3、手机分辨率是大于1920 * 1080,则会将图片等比缩小 加载;

总结:
当图片放置在不同drawable文件夹中,且只有这一张图片时,运行设备会根据自身的屏幕密度,对图片进行放缩,放缩比例符合前面图上的规则
图片文件的大小与在内存中占用的大小没关系,内存中实际占用大小与图片分辨率、像素显示参数有关

所以,在一个App里面使用一套UI理论上应该是没有问题的,但是要注意:
最好使用较高分辨率的切图,并且放置在正确的drawable文件夹中,比如按照xxhdpi的分辨率进行切图,放置在drawable-xxhdpi中
对于可以使用.9格式的图片,最好使用.9,减少资源大小
如果有条件,最好提供多套UI切图。如果只有一套切图,系统需要对图片进行压缩,会进行大量运算,影响设备性能。同时,在某些情况下,系统对图片的压缩会可能会出现锯齿,造成信息的丢失
如果是多套切图的话,最好不要直接用工具按照比例放缩,这样小图标会丢失一些细节。当然,这部分是美工来做的,可以让她参考这篇文章利用PS CS6的新功能保持ICON细节饱满完美

思考一下,如果把一个本来应该放在drawable-xxhdpi里面的图片放在了drawable文件夹中会出现什么问题呢?
明明是(4/4)变成了(12/4) 导致 在xxhdpi设备上,图片会被放大3倍,图片内存占用就会变为原来的9(3*3)倍!

2.图片加载顺序

图片资源查找流程.png

比如在一个中等分辨率的手机上,Android就会选择drawable-mdpi文件夹下的图片,

  1. 文件夹下有这张图就会优先被使用,在这种情况下,图片是不会被缩放的;
  2. 但是如果没有在drawable-mdpi的文件夹下找到相应图片的话,Android系统会首先从更高一级的drawable-hdpi文件夹中查找,如果找到图片资源就进行缩放处理,显示在屏幕上;
  3. 如果drawable-hdpi文件夹下也没有的话,就依次往drawable-xhdpi文件夹、drawable-xxhdpi文件夹、drawable-xxxhdpi文件夹、drawable-nodpi;
  4. 如果更高密度的文件夹里都没有找到,就往更低密度的文件夹里寻找,drawable-ldpi文件夹下查找;
  5. 如果都没找到,最终会在默认的drawable文件夹中寻找,如果默认的drawable文件夹中也没有那就会报错啦。(前提是把一张图片做成很多不同的分辨率放在各个对应密度的drawable文件夹下)

举个例子,假如当前设备的dpi是320,系统会优先去drawable-xhdpi目录查找,如果找不到,会依次查找xxhdpi → xxxhdpi → hdpi → mdpi → ldpi。
对于不存在的drawable-[density]目录直接跳过,中间任一目录查找到资源,则停止本次查找。

float xdpi = getResources().getDisplayMetrics().xdpi;
知道设备的dpi后就知道设备首先会在哪个drawable文件夹下去寻找了:dpi范围密度对应范围
设备密度 适配资源文件密度 放大倍数
0dpi ~ 120dpi ldpi 0.75
120dpi ~ 160dpi mdpi(基线BaseLine) 1.0
160dpi ~ 240dpi hdpi 1.5
240dpi ~ 320dpi xhdpi 2.0
320dpi ~ 480dpi xxhdpi 3.0
480dpi ~ 640dpi xxxhdpi 4.0

总体匹配规则就是这样:

  • 如果图片所在目录dpi低于匹配目录,那么该图片被认为是为低密度设备需要的,现在要显示在高密度设备上,图片会被放大。
  • 如果图片所在目录dpi高于匹配目录,那么该图片被认为是为高密度设备需要的,现在要显示在低密度设备上,图片会被缩小。
  • 如果图片所在目录为drawable-nodpi,则无论设备dpi为多少,保留原图片大小,不进行缩放。

例如,当前设备的dpi是480(即xxhdpi),那么对于存放于mdpi目录中的图片会被放大三倍。
对于很多设备,其dpi并不刚好是六种通用密度最大dpi,这种情况下,图片的缩放倍数如何计算呢?
scale = 设备dpi/ 图片所在Drawable目录对应最大dpi。

3.dpi计算方式:

密度(dpi,dots per inch;或PPI,pixels per inch)。
从英文顾名思义,就是每英寸的像素点数,数值越高当然显示越细腻。
假如我们知道一部手机的分辨率是1080×1920,屏幕大小是5英寸,你能否算出此屏幕的密度呢?
哈哈,中学的勾股定理派上用场啦!通过宽1080和高1920,根据勾股定理,
我们得出对角线的像素数大约是2203,那么用2203除以5就是此屏幕的密度了,计算结果是440。
440dpi的屏幕已经相当细腻了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容