在安卓开发中关于屏幕适配是绕不开的话题。十几年了依然会有各种各样的问题。今天我想用自己的理解记录下屏幕适配的问题。
单位:
1英寸=2.54厘米
ppi :一英寸的屏幕密度(这里的屏幕密度不是一英寸有多少个像素点总和而是在一英寸的正方形上排列了多上行和列)
px :像素这里是ps 或者屏幕常用单位
dp:安卓开发时候的相对单位
dp与px 转换:安卓规范中1英寸的屏幕可以放160*160个像素点的屏幕是1倍屏幕:即1px=1dp
这里说的密度并不是有多少个像素点的和。而是有多少行和列
密度计算公式:(√(宽px²+高px²))/屏幕对角尺寸
密度计算原理是:px与对角尺寸不是一个单位,我们可以根据勾股定理求出在弦的大小像素排布行列个数,因为弦就是屏幕对角。这样知道了弦对应大小的屏幕上有多少个像素就可以求出一英寸屏幕的密度了。
根据勾股定理求弦上有多少个像素后/对角尺寸就能得到一个在一英寸的正方形中应该有多少个像素行列排布。
存在问题:安卓屏幕适配难题主要存在手机宽高比不一致。
dp 能解决的问题:在一英寸宽高下的屏幕用160dp 能占满这个1英寸的屏幕 。以及同宽高比例但是密度不同且比例一致的问题。
dp无法解决同比例手机不同尺寸不一致问题,以及手机尺寸比例与像素比例不一致问题
例如:16:9手机1的是(长6.3英寸:宽3.55英寸:对角7.2英寸)7.2英寸手机
16:9手机2的是(长16英寸:宽9英寸:对角18.35英寸)18.35英寸手机
示例1:1080*1920(16:9)在7.2寸下是标准的1.91倍需要565.4才能填充满
示例2:1440*2560(16:9)在7.2手机下是标准的2.55倍,需要564.7dp 才能填充满
示例3:1440*3000( 18.75:9)在7.2寸手机下是标准的2.88倍,需要500dp 才能填充满
示例4:1440*2560(16:9)在18.35寸(16:9:18.35)手机上是标准的1倍,需要1440dp 才能充满
情况 |
长宽不变与像素不同但是像素比例一样 |
1英寸正方形下像素数量不同 |
尺寸比例相同但尺寸大小不同 且像素比例相同 |
手机尺寸比例与像素比例不同 |
Dp 能否解决 |
√ |
√ |
x |
x |
对比 |
示例1与示例2 |
示例2与示例4 |
示例4(这种情况基本不出现,这样显示屏幕可能是瘪的) |
综上所述:dp可以解决像手机尺寸比例和像素比例相同且像素数量的不同问题。为什么安卓不能解决相同像素下。不同尺寸无法适配?
安卓屏幕宽度有n 个1英寸宽的屏幕,所以导致同样是1080px宽手机,在3倍下在360dp 能占满手机屏幕,在2.75下就会有空余,
主要是因为1080px中可以有三倍下有1080/(160*3)=2.25英寸,
在2.75倍中1080/(160*2.75)=2.45英寸,综上所述同样是1080px宽但是在3倍屏幕下360dp就能铺满屏幕,而在2.75倍下需要大约393dp才能铺满
今日头条适配思路:
通过修改density由原来与安卓标准每英寸160px 的基准,修改为依照设计图的density 为基准。
例如:设计图是3倍的1080,那么
新density=手机实际px/(1080/3),这样就能达到设计图与效果一致
//实现一个手机尺子的思路:由此可以发现,手机实际ppi 与系统ppi 可能存在有出入不一致的情况。具体原因不清楚。以下计算中因小数等问题可能误差几px或者几微米则应该认为一致。
屏幕:1080*2340对角线长度6.39英寸
安卓标准是1英寸下160px,一厘米应该是62.99px约等于63px=63dp
1英寸=2.54厘米
正常计算ppi: 402.69px density:2.52
系统ppi:440:density:2.75
正常计算:
长度/(安卓标准px*density)*英寸转厘米
2340/160/2.52*2.54=14.74厘米
1英寸=2340/14.74=158.75px
1cm=2340/14.74/2.52=62.99dp
系统提供的:440dpi density:是440/160=2.75
2340/440*2.54=13.5厘米
1英寸=2340/13.5=173px
1cm=2340/13.5/2.75=63dp
为什么计算的一个14.74里面,另一个是13.5厘米 ,而且最终1厘米下都是63dp?
答:因为计算英寸时候使用的密度不一样。当1英寸一个密度比另一高的时候,最终在转化为厘米的dp时候缩放更小。
结论:虽然1cm 都是63dp 但是整体上系统提供的会短1厘米。所以不够准确。
系统提供的错误的与实际差距:
每英寸差距px*总应英寸=总差距Px /错误的英寸px*2.54=误差
(440-403)*5.8=214.6px/440px*2.54= 1.23cm
Var dm = resources.displayMetrics
dm.densityDpi这个是系统的ppi
dm.density这个是系统的ppi/160标准的倍数
dm.scaledDensity这个是系统的ppi/160标准的倍数
dm.widthPixels :屏幕宽度px
dm.heightPixels:屏幕高度px通过resources.displayMetrics或者newDisplayMetrics(),以及 getWindowManager().getDefaultDisplay().getMetrics(dm);方式进行获取dm值返回的是可使用的高度,这里应该是减去了导航栏跟状态栏的高度了。
如果想获取真实高度需要:getWindowManager().getDefaultDisplay().getRealMetrics(dm);
dm.ydpi这个是真实的屏幕1英寸下y轴的ppi
dm.xdpi这个是真实的屏幕1英寸下x轴的ppi
关于微信小程序rpx:
rpx:是通过吧手机宽度px 平分750份得到的px 作为1rpx
关于rpx与dp 区别
rpx与dp 的区别:dp 是英寸为基础。rpx 则是屏幕宽度为基础。