使用 gomobile 检测 华为荣耀 6 Plus 的屏幕大小为: 1080*1776 px ; 162pt*266.40pt ; 每pt像素个数:6.666665个。
而实际的数据是:
主屏尺寸: 5.5英寸; 分辨率 1920*1080 像素 ; 像素密度 401ppi。
实测 1776,而不是 1920 是因为 华为荣耀 有一个可隐藏的 按钮区, 实测时按钮区是存在的,排除了按钮区的高度就是 1776 。
另外,它5.5英寸的屏幕,手机屏幕以16:9,大概长12.18,宽6.85,对角13.97厘米。 按照 1英寸 = 2.54cm = 25.4 mm = 72 pt = 6pc 来说 ,它的 pt 值应该是:
194.17pt * 345.26pt 大小,但实测 162pt*266.40pt , 这个误差到底在哪里? 就是本文要分析的内容。
dpi、ppi
这两个概念在计算机领域是相同的。
dpi (dots per inch)
打印分辨率 (每英寸所能打印的点数,即打印精度)
DPI(Dots Per Inch)是印刷行业中用来度量空间点密度用的,这个值是打印机每英寸可以喷的墨汁点数。
ppi(Pixels Per Inch)
图像分辨率 (在图像中,每英寸所包含的像素数目)
即每英寸所拥有的像素数目,屏幕像素密度。
计算机显示设备从打印机中借鉴了DPI的概念,由于计算机显示设备中的原子单位不是墨汁点而是像素,所以就创造了PPI(Pixels Per Inch),这个值是屏幕每英寸的像素数量,即像素密度(Screen density)。
如160dpi指手机水平或垂直方向上每英寸距离有160个像素点。假定设备分辨率为320*240,屏幕长2英寸宽1.5英寸,dpi=320/2=240/1.5=160
Android 对不同dpi屏幕的适配
android 屏幕的碎片化太杂,对屏幕的适配就采用了分段出来,不同 dpi 的分大类如下图:
根据这些不同的大类,用户提供不同的资源图片,系统自动去对应大类下获得相应资源。下图的最后部分是相对于 基准值160 dpi(mdpi) 的图片放大倍数。
需要注意的是: 每一种dpi对应一个dpi范围,480dpi包括400dpi~560dpi,比如:Samsung S4的dpi为441,虽然没到480,但它属于xxhdpi(480dpi)这个标准。
荣耀 6 Plus dpi 为 401 (计算方法如下),它接近480dpi,所以系统会优先为它选择xxhdpi目录下的素材。
对角线是5.5英寸,因像素相对于英寸足够小,我们可以根据勾股定理,计算出对角线上大约有2202.907像素,再用这个像素数除以5.5英寸大致得到像素密度为:400.528, 约等于401。所以此处屏幕像素密度为:401ppi。
参看: http://www.jianshu.com/p/0296fada6df3
就近取ppi值的适用于所有机型的Android设备,如下图一些之前设备的取值:
gomobile 获取屏幕大小pt值的算法
WidthPt, HeightPt geom.Pt
的值是通过首先计算 PixelsPerPt(每Pt多少个像素),然后根据像素计算具体的pt值得来的。
golang.org/x/mobile/app/darwin_amd64.go 文件中有下面代码:
PixelsPerPt 的值则是 ppi/72 算出来的。
代码在: golang.org/x/mobile/app/android.go
android 的ppi或者dpi计算代码如下,也是上面文件:
这里用 Android NDK 的方法 AConfiguration_getDensity 返回的是当前手机的屏幕 dpi 类型, 就是上面的 dpi 的大分类, 可有的值如下:
然后这里使用的 dpi 不是手机屏幕真实的 dpi, 而是根据上面大类对应的dpi。
按照这个逻辑, 上面荣耀 6 Plus 的 宽的两个值就能对应出来了:
- 1080 /(401/72) = 193.9 pt
- 1080/(480/72) = 162 pt
gomobile 是按照 480 ppi 计算的, 但是它的实际 ppi 是 401 。
iOS 系列的pt计算
计算相关代码在 golang.org/x/mobile/app/darwin_armx.go
参考:
Android 屏幕适配
http://stormzhang.com/android/2014/05/16/android-screen-adaptation/