1.1 px
我们可以看到现在市面上的手机分辨率截止到2018-05月,统计为:
这里额外提一下,类似1080 x 1812,720 x 1184 等看着很奇怪的结尾不是0的分辨率,大部分是因为有虚拟键的原因,虚拟键占去了一部分高度。
以1080 X 1920为例,它代表的是手机上的像素点,
类似这种,表示横着有1080个像素点,竖着有1920个像素点,所以1080 X 1920 代表了手机在横向、纵向上的像素点数总和
所以如果我们写了一个Button,假设高度和宽度都为10px , 则说明在这个屏幕点上高宽都占了10个点。
1.2 inch(屏幕尺寸)
手机屏幕的物理尺寸,我们经常听到有人说我买的是iPhone 8 plus,尺寸是5.5的屏幕,iPhone 8尺寸是 4.7的。其实它们所带的单位都是inch(英寸), 1(inch)≈2.54(cm)
所以屏幕尺寸就是按屏幕对角测量的实际物理尺寸。 为简便起见,Android 将所有实际屏幕尺寸分组为四种通用尺寸:小、 正常、大和超大。
1.3 dpi
屏幕物理区域中的像素量;通常称为 dpi(Dots Per Inch 每英寸 点数)。所以看标题就知道,他更像是在求一个密度。那我们既然知道了手机屏幕对角线的尺寸,我们只要知道了手机对角线上的px数量,除一下就知道了每英寸上的像素点数了。
所以我们只需要通过勾股定理获取对角线上的像素值,再除以屏幕尺寸值就可以了。
为简便起见,Android 将所有屏幕密度分组为六种通用密度: 低、中、高、超高、超超高和超超超高。
六种通用的密度:
- ldpi(低)~120dpi
- mdpi(中)~160dpi
- hdpi(高)~240dpi
- xhdpi(超高)~320dpi
- xxhdpi(超超高)~480dpi
- xxxhdpi(超超超高)~640dpi
1.4 dp 和 density
其实dp 本来是叫dip (Density Independent Pixels),所有有时候面试的别人,面试者会弄错,把dip当做了dpi,所以你问他请说下 dp 和 dip ,他会把 dip说成dpi的内容。
我们举例说下这块知识点: 要画一个 高和宽各为屏幕的一般的按钮,我们假设有二块屏幕,一块是100 X 100 ,一块是 200 X 200 ,那这时候第一块的屏幕上我们写Button 应该为:
第二个屏幕的Button应该为:
这样是不是都各自占了屏幕的高宽的一半,但是假如有第三个屏幕 300 X 300 呢,难不成再写一个Button的高宽值? 所以我们可以用一种单位来代替,但是这种单位可以在不同的屏幕环境下,值是不同的。比如我们就把这个单位当做“haha”。
比如我们现在都这么写:
这时候在100 x 100的时候, 50haha = 50px ,在200 X 200 屏幕的时候 , 50 haha = 100px , 在 300 X 300 屏幕的时候,50haha 等150px。
这个感觉就很像你跟别人说我欠你50 money,如果在中国,代表你欠别人50元人民币,但是如果在美国,你这么说,指你欠50美元,也就是欠了三百多元人民币。(这个例子不要跟我较真,我就意思意思而已)
所以dp就是类似我们上面自己定义的haha这个单位。
比如50dp = 50px ,这时候1dp = 1px , 50dp = 100px的时候 是 1dp = 2px ,所以我们可以看到倍数分别为 1 和 2 ,我们用density来代表这个倍数。也就是说: dp * density = px,这时候就是 50 dp * 1 = 50px , 50dp * 2 = 100px
(就像是我说我欠你50 money,在中国,这个density就是1 , 也就是欠你50元人民币,在美国可能就是指300多人民币,这个density也就是 美元换算成人民币的倍数)
那么这个density具体是怎么来的呢?其实很简单,记不记得我们前面说过dpi ,也就是屏幕的密度,我们就用这个密度来做比较,比如我们 把160dpi 作为标准,那另外一个手机是320dpi ,那么这个density就是 (320/160 = 2)。 所以我们再次把公式 : dp * density = px 转变为: dp * (dpi / 160) = px
那么为什么用160dpi作为标准呢,以前看到文章提过:mdpi基于第一款 Android 设备 ″T-Mobile G1″ 的屏幕配置(缩放系数scale=1)。
1.5 基础知识小结
所以假如我们现在的手机分辨率知道了,手机屏幕尺寸也知道了。我们通过公式求出 dpi ,然后 dpi / 160 就是当前手机的density,然后我们就知道我写了1dp 在这台手机上具体是多少px了。
具体的安卓手机尺寸四个分类及6中dpi分类:
我们的某台手机的dpi,density,分辨率等如何获取呢,:
DisplayMetrics mDisplayMetrics = getResources().getDisplayMetrics();
//横向分辨率
int width = mDisplayMetrics.widthPixels;
//竖向分辨率
int height = mDisplayMetrics.heightPixels;
//density值
float density = mDisplayMetrics.density;
//dpi的值就等于density * 160
float dpi = density * 160;
也许有人说,那我们使用dp不是已经完美的实现了各种兼容性吗,就像我们上面提到过的,100 X 100 ,200X200 , 300 X 300的屏幕,我们都只要写50haha, 就分别代表了50,100,150,不是就占了各自屏幕的一半了么。理论上的确是这样,但是我们刚提过我们的density是等于 (dpi / 160),而dpi又由分辨率和屏幕尺寸同时决定,安卓手机的碎片化太过严重,所以很多手机虽然分辨率不同及屏幕尺寸不同,造成最后的dpi一样,所以最后的density也一样,就造成了适配实现不全。假设我们多了一个400X400 的设备,因为它的屏幕尺寸也同时变大了很多,所以最终的density和300X300一样,那这时候我们写了50haha,也就代表了150px,这时候明显在400X400上面并没有显示为一半,甚至当这个400X400的设置的屏幕尺寸超级大,反而可能算下来的density与100X100的一样,那这时候50haha可能就只有50px,则显示差距就更大了。 (其实主要原因就是dpi不是单独由分辨率来决定,同时还有屏幕尺寸影响,所以二个变量同时作用,造成不同分辨率的手机最后的density也可能相同。这样dp转换成的px也就相同了,但是手机的分辨率本身有不同,这时候就会出现适配不对。)
2 各类适配方案
2.1 生成分辨率values文件夹
因为我们上面提过 , px = (dpi / 160) * dp, 但是dpi又是同时由分辨率和屏幕尺寸同时决定,造成了不同的分辨率,dpi可能一样,这样最终得到的px一样,比如都是占屏幕的一半,300X300得到的可能是150,但是400X 400得到的也是150,这时候就不对了。
那我们就想到了。我们能不能不是同时受到分辨率和屏幕尺寸决定,而是只受一个因素来影响,这样就是真正的按比例来了。比如300X300是150,400X400是200,500X500是250,是只受分辨率的影响,所以分辨率大的,最终得到的结果一定就大。所以我们就不能使用dp了。而是一个新的单位,而这个单位是根据不同的分辨率,得到不同的值,那怎么计算呢,就是穷举法,比如刚才的300X300,我们规定1 haha等于1 px,然后再600 X 600里面,1 haha 等2 px , 1200X1200里面是 1 haha 等于 3 px 。所以我们在不同分辨率下的values文件夹下写上不同的值:
300X300下
1px
600X600下
2px
1200X1200下
3px
所以这个就是方案1 ,附上文章链接。
Android 屏幕适配方案 我们可以看下面的图:
我们可以看到列举了所有可能的屏幕分辨率的values,然后手动按照倍数,进行相应的赋值。当然这些文件不可能手写,通过Java自动生成相应的文件:
这样最终影响结果的就只是分辨率的了,分辨率越大的,x1的值越大。
但是这个方案有一个致命的缺陷,那就是需要精准命中才能适配,比如1920x1080的手机就一定要找到1920x1080的限定符,否则就只能用统一的默认的dimens文件了。而使用默认的尺寸的话,UI就很可能变形,简单说,就是容错机制很差。
2.2 生成values -sw 文件夹
可以参考:
骚年你的屏幕适配方式该升级了!-smallestWidth 限定符适配方案
其实这个方式跟上面的2.1方法原理可以说一模一样。唯一的区别就是使用了sw来保证一定的容错性。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
尾声
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
ecb71ac0)
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算