关于Android开发中如何使用dp表示长宽
本文正文在第二、四小节,第一、三小节可略过不看。
1. 使用px替代dp进行开发存在的一些问题
虽然网上有使用px替代dp进行开发的技巧,比如鸿洋大神的这篇文章,但存在以下问题:
- 需要建很多分辨率目录:
- 虽然是用脚本工具自动生成的,但是看着长长的一串还是很吓人:
- 比较占用资源
- 对于一些奇葩分辨率(虽然现在已经不常见了)还需要做额外的适配工作
所以使用px来替代dp还是有一些不方便的,那么用回dp的话,在开发过程中有以下问题需要考虑:
- 怎么知道我的模拟器的屏幕总宽度、总高度是多少dp呢?
- 怎么方便地把设计师用px标注的数值转化成dp值呢?
我们知道设计师在设计Android应用时用的是720x1280
的画布,也就是说总宽度是720px,总长度是1280px。这个其实输出的是2倍切图。
另外也有设计师使用的是360x640的画布,比如Mockplus设计软件在新建文件时的默认选项:
这个是一倍切图。
现在本文介绍的方法是根据一倍切图的比例进行“1:1”的换算,也就是你的设计图用360px表示屏幕总宽度,那么我在开发中用360dp也能充满屏幕总宽度。
2. 选用合适的Android模拟器设备
使用Pixel(5.0inch 1080x1920 xxhdpi)设备作为默认的Android模拟设备,360dp即表示屏幕总宽度,640dp表示屏幕总长度。如图所示:
3. 不同设备dp-px换算及显示同一图形对比
设备规格:
设备 | 规格 | PPI (DPI) | 理论换算 | 趋近取值(屏幕像素密度等级) |
---|---|---|---|---|
Redmi Note 2 | 5.5inch 1080p | 400.53 | 1dp = 2.50px | 480dpi (xxhdpi) |
Nexus 5X | 5.2inch 1080p | 423.64 | 1dp = 2.65px | 480dpi (xxhdpi) |
Pixel | 5.0inch 1080p | 440.58 | 1dp = 2.75px | 480dpi (xxhdpi) |
备注:屏幕像素密度等级:
范围 | 等级 | 倍率 | 换算关系 |
---|---|---|---|
~160dpi | mdpi | x1 | 1dp = 1px |
~240dpi | hdpi | x1.5 | 1dp = 1.5px |
~320dpi | xhdpi | x2 | 1dp = 2px |
~480dpi | xxhdpi | x3 | 1dp = 3px |
~640dpi | xxxhdpi | x4 | 1dp = 4px |
显示测试对象:测试两个ImageView,View(a)是360dp的正方形,View(b)是48dp的正方形。
设备 | 截图 | 理论换算A | 实际显示A | 理论换算B | 实际显示B | 备注 |
---|---|---|---|---|---|---|
Redmi Note 2 | 暂无 | 360dp = 900px | 暂无 | 48dp = 120px | 暂无 | 后面会说 |
Nexus 5X | 见下图1 | 360dp = 954px | 945px | 48dp = 127.2px | 126px | |
Pixel | 见下图2 | 360dp = 990px | 1080px | 48dp = 132px | 144px | View (a)宽度刚好填满屏幕 |
值得注意的是Nexus 5X宽度并没有填满屏幕,而Pixel则刚好填满。这是为什么呢?
通过下图可以发现,原来我们之前趋近取值时写错了:
那么为什么要选“420”呢,这个数字有什么特殊含义?
这是因为5X是423.64 PPI,离420比较近,离480比较远。
这时有人会问,照这样说的话,谷歌自己定好的像素密度等级连自家设备都不遵守,那大家是不是都可以随便取了呢?
比如我的红米Note2手机(400.53 PPI)离400dpi更近,而且还正好是mdpi的2.5倍,换算起来也很方便!
实际上红米Note2是不是取400dpi了呢:
可见并没有。
从这张表来看,“420”确实可以说是比较“奇怪”了:
范围 | 屏幕像素等级 | 倍率 | 换算关系 | 备注 |
---|---|---|---|---|
~160dpi | mdpi | x1 | 1dp = 1px | |
~240dpi | hdpi | x1.5 | 1dp = 1.5px | |
~320dpi | xhdpi | x2 | 1dp = 2px | |
x2.5 | 1dp = 2.5px | 不使用 | ||
~420dpi | x2.65 | 1dp = 2.65px | Nexus 5X, Pixel 2… | |
~480dpi | xxhdpi | x3 | 1dp = 3px | |
~560dpi | x3.5 | 1dp = 3.5px | Nexus 6, Nexus 6P, Pixel XL, Pixel 2 XL… | |
~640dpi | xxxhdpi | x4 | 1dp = 4px |
另外还有两个问题我们没有提到,一个是很多几年前的机型根本就不把屏幕像素等级当回事,另一个是即便是采用标准屏幕像素等级的设备,其长宽比也不一定是16:9(比如mdpi和hdpi的很多机型都是3:2或者5:3的长宽比)。这两个原因也就造成了即便是用dp作为单位,仍然会出现各种设备(主要是旧设备以及Nexus、Pixel XL)显示的效果不尽相同的问题。
那么我们在开发中如何去适配呢?
假如我们就按照360dp为屏幕宽度、640dp为屏幕高度,那么如何让Nexus 5X也显示为充满屏幕宽度呢?
4. 针对旧设备、420dpi、560dpi机型的屏幕适配
范围/dpi | 典型分辨率/px | 屏幕长宽比 | 屏幕总宽度/dp | 备注 |
---|---|---|---|---|
~160 (mdpi) | 320 x 480 | 3 : 2 | 320 | 标准像素密度等级。比较老的设备 |
360 x 640(一倍切图) | 16 : 9 | 360 | 貌似没有这个分辨率的手机 | |
~240 (hdpi) | 480 x 800 | 5 : 3 | 320 | 比较老的设备,比如Nexus One/S… |
~320 (xhdpi) | 720 x 1280(二倍切图) | 16 : 9 | 360 | 主流手机(2014-2016) |
~420 | 1080 x 1920 | 16 : 9 | 411.4 | 多见于Google家的设备Nexus系列 |
~480 (xxhdpi) | 1080 x 1920(三倍切图) | 16 : 9 | 360 | 主流手机(2014-2017) |
~560 | 1440 x 2560(2k) | 16 : 9 | 411.4 | 多见于Google家的设备Nexus、Pixel XL… |
~640 (xxxhdpi) | 1440 x 2560(四倍切图) | 18.5 : 9 | 360 | 三星S8/+… |
适配方法(一):
根据@zly394 的方法:
为了适配480x800的手机屏幕,需要设计师在切图的时候也要切出一套hdpi的图,并且是480*800分辨率下的hdpi的图。
另外在写布局文件设置宽度的时候,也要需要考虑这个差值,hdpi下的dp宽度应该是xhdpi或xxhdpi下的dp宽度的0.8~0.9倍。
(Android屏幕适配—被偷走的dp - 简书 http://www.jianshu.com/p/584ac569ffc3)
也就是说为这些旧设备分辨率专门制作切图资源。
适配方法(二):
使用第一小节提到的方法,即新建多个对应的分辨率目录,把各种奇葩、少见、独特的分辨率都做好相应的换算关系表,缺点是比较麻烦,有种吃力不讨好的感觉,好处就是一劳永逸,以后的项目可以复用。
具体可参考以下两篇文章:
- Android屏幕适配全攻略(最权威的官方适配指导) - CocoaChina_让移动开发更简单 http://www.cocoachina.com/android/20151030/13971.html
- Android 屏幕适配方案 - Hongyang - ****博客 http://blog.****.net/lmj623565791/article/details/45460089
适配方法(三):
同样是比较妥协的方法,那就是在写布局的时候多使用match_parent、权重以及百分比布局,小心地使用dp数值,可以避开大多数的坑。
然后一边等着时间慢慢淘汰掉各种奇怪的分辨率机型,最后花点精力给谷歌家比较重要的两类产品:①1080x1920,420dpi
(Nexus 5X、Pixel 2);②1440x2560,560dpi
(Nexus 6、Nexus 6P、Pixel XL、Pixel 2 XL)按照方法二建好相应的分辨率文件夹就好了。
相关阅读
- 一直困扰设计师多年的Android …-UI中国 http://m.ui.cn/details/45435
- Android屏幕适配—被偷走的dp - 简书 http://www.jianshu.com/p/584ac569ffc3
- 网上流传的dp、px换算公式是正确的吗? - 知乎 https://www.zhihu.com/question/33312136
- 一款APP,从设计稿到切图(Andr…-UI中国 http://m.ui.cn/details/79573
- Android 屏幕适配方案 - Hongyang - ****博客 http://blog.****.net/lmj623565791/article/details/45460089
- [Android] 在xml中“直接”使用px的小技巧和工具 - 点点滴滴 - SegmentFault https://segmentfault.com/a/1190000006856314
- 最简单也最难——怎样获取到Android控件的高度 - yxwkaifa - 博客园 https://www.cnblogs.com/yxwkf/p/5221684.html
- Android屏幕适配全攻略(最权威的官方适配指导) - CocoaChina_让移动开发更简单 http://www.cocoachina.com/android/20151030/13971.html