内容简介:手上有两个真机: oppoA77(再加一台模拟器(辅助:一台笔记本电脑联想Y480N(
手上有两个真机: oppoA77( 1920*1080 5.5英寸
)、 oppoR15X( 2340*1080 6.4英寸
) 、
再加一台模拟器( 480*320 3.5英寸
)仿OPPO R801
辅助:一台笔记本电脑联想Y480N( 768*1366 14英寸
) 和一个iPad_Air_2( 2048*1536 9.7英寸
)
1.按照像素来算引出的问题(反证法):
如果
,我说 如果
一个像素代表n个物理毫米,当n等于1时
那么oppoR15X( 2340*1080
)相当于 23.4*10.8cm
,量了一下,大概跟书差不多
OPPO R801( 480*320
)相当于( 4.8*3.2cm
),量了一下,差不多跟橡皮一样大
在同一参考系下,玩oppoR15X和OPPO R801,相当于玩一本书和玩橡皮的区别
显然我并没有这样的体验,这只能说明,对于两个不同的手机,它们的n值不同
也就是两个手机: 1个物理毫米中所含的像素个数是不同的
2.手机英寸的概念
英寸是衡量手机屏幕的真实大小
我们买手机一般关心的是手机是多少多少英寸的,然后懂行的看看分辨率,那英寸代表什么?
1英寸 = 2.54 厘米
: 大概和一元硬币的直径差不多,不信你拿六个硬币排在对角线比一下
由于分辨率确定了长宽比,我们不难算出oppoR15X和OPPO R801的物理宽高
\ | 宽px | 高px | 对角线in | 对角线cm | 物理宽cm | 物理高cm |
---|---|---|---|---|---|---|
oppoR15X | 1080px | 2340px | 6.4in | 16.256cm | 6.81cm | 14.76cm |
OPPO R801 | 320px | 480px | 3.5in | 8.89cm | 4.93cm | 7.40cm |
3.屏幕属性的封装
这么多属性,一个一个算也怪累人的,计算器点着也不爽,封装一下吧 ScreenInfo.java
/** * 作者:张风捷特烈<br/> * 时间:2018/12/1 0001:8:01<br/> * 邮箱:1981462002@qq.com<br/> * 说明:屏幕尺寸信息 */ public class ScreenInfo { public static final float INCH_TO_MM = 25.399999961392f;//英寸转为毫米数 public String name;//设备名称 public float inchC;//英寸 public int pxW;//屏幕宽像素数 public int pxH;//屏幕高像素数 public int pxC;//对角线像素数 public float ppi; public float dpi; public float relW;//实际宽度 public float relH;//实际高度 public float relC;//实际对角线长度 public ScreenInfo() { } public ScreenInfo(String name, float inchC, int pxH, int pxW) { this.name = name; this.inchC = inchC; this.pxW = pxW; this.pxH = pxH; pxC(); ppi(); dpi(); relC(); relW(); relH(); } private int pxC() { pxC = (int) Math.sqrt(pxH * pxH + pxW * pxW); return pxC; } private float ppi() { ppi = pxC() / inchC; return ppi; } private float dpi() { dpi = pxC() / inchC; return dpi; } private float relW() { relW = relC * (pxW * 1.f / pxC()); return relW; } private float relH() { relH = relC * (pxH * 1.f / pxC()); return relH; } private float relC() { relC = inchC * INCH_TO_MM; return relC; } @Override public String toString() { return "ScreenInfo{" + "\nname='" + name + '\'' + "\n, 屏幕尺寸/英寸=" + inchC + "\n, 屏幕横向像素数=" + pxW + "\n, 屏幕纵向像素数=" + pxH + "\n, 屏幕对角线像素数=" + pxC + "\n, ppi=" + ppi + "\n, dpi=" + dpi + "\n, 屏幕对角线物理尺寸/mm=" + relC + "\n, 屏幕横向物理尺寸/mm=" + relW + "\n, 屏幕纵向物理尺寸/mm=" + relH + '}'; } } 复制代码
好吧,知道大家不喜欢看数据,于是我自定义了一个View,用ScreenInfo信息画个图示,感觉还蛮好的
三行代码就能画一个手机信息图,也不是很难,有兴趣的可以看看源码,或自己画画
我是按照物理尺寸画的,所以现实中它们的 屏幕
相对大小就是这样的!
如果你想玩,其他的屏幕也可以试试:只要知道分辨率和多少英寸
4.密度:
什么是密度?----紧密程度? 上学的时候应该听过线密度,面密度和体密度、或者人口密度吧。 比如一个市的人口密度:合肥市面积为11445.1平方公里,人口为779万,人口密度为680.6人/平方公里 也就是合肥市平均 1平方公里 有680.6人 复制代码
现在把屏幕当做土地,把像素点当做人,这些人一个一个有秩序地排着 那么OPPOR15X中1mm的长度排多少个像素,显而易见:2577px/163mm = 15.809... 取个整 15.8 那么 1 平方毫米能容下几个像素呢? 15.8*15.8 = 249.64个/mm^2 约250个/mm^2 那么OPPOR801中1mm的长度排多少个像素,显而易见:2577px/163mm = 6.471... 取个整 6.5 那么 1 平方毫米能容下几个像素呢? 6.5*6.5 = 42.25个/mm^2 约42个/mm^2 相当于在一片等大的土地上,一块占了250个人,一块占了42个人,神奇的是两边都把这块地占满了 于是真相(得出的结论)只有一个:两块土地上一块是小人,一块是巨人 复制代码
现在把物理尺寸:1mm的屏幕放大
记得小时候的手机肉眼就能看到一点一点的像素,就是因为1mm里的像素点少,相对而言一粒像素就大
现在的手机可是瞅不出来像素了
5.ppi与dip
现在我们手上的信息还蛮多的,这些信息有什么用?
ppi(Pixel Per Inch),即每英寸的像素。
我们刚才好像算了每毫米的像素数,那每英寸的像素数能难倒你吗? OPPO-R15X 的 ppi : 2577px/6.4in = 402.65625 px/in 约402.6ppi OPPO-A77 的 ppi : 2202px/5.5in = 400.363... px/in 约400.4ppi OPPO-R801 的 ppi : 576px/3.5in = 164.571... px/in 约164.6ppi 复制代码
ppi形象一点的比喻:
一个一元硬币直径约1 in,现在让一元硬币(包括背景)等大显示在三个手机上:
OPPO-R15X需要用:402*402=161604 个像素点
OPPO-A77需要用:
400*400=160000 个像素点
OPPO-R15X需要用:
164*164=26896 个像素点
我们知道像素组成了显示的图片,也就是说用161604个点和26896个点组成相同的画面
那么26896的那个看起来效果自然要比161604的差很多,161604更加紧密,所以视觉感好
来分析一下笔记本电脑:
ppi=1567/14=111.928...
,也就是 1 in 里有112个点, 1 in = 25.4mm
那说明一个像素的大小是 25.4 / 112 = 0.226mm
,人眼可视长度是0.1mm,所以你近些看可以看到颗粒
dpi(Dot Per Inch),即每英寸的点数。
dpi又是什么鬼,点数又是什么鬼?---dpi称为打印精度 打印机将[彩色液体油墨]经喷嘴变成细小微粒喷到印纸上,一个颗粒代表1点 dpi的意思是每英寸墨滴点数,比如300dpi的意思就是每英寸墨滴的个数为300 用300个点表示一个硬币,和72个点表示一个硬币,可想而知300的更加精细 大学时做要打印的ps产品效果图都要把图片的dpi调到300以上,因为大幅的海报需要细致的像素表达 普通的web图片只要求72dpi就够了,因为只是显示在屏幕上而言 复制代码
ppi和dpi在Android
Android又不是打印机,dpi和ppi等价,都是表示 1 in长度对应的px数 也许谷歌更倾向于用`点(dot)` 来表述屏幕像素,所以采用dpi的说法而不是ppi 复制代码
二、谁动了我的图片尺寸?
1.我的 250*200的图片
画出来怎么尺寸不对?----Q1
实验图片: 250*200,300dpi,res\mipmap-xhdpi\wy_250px_200px_300dpi.jpg
实验图片: 250*200,72dpi,res\mipmap-xhdpi\wy_250px_200px_72dpi.jpg
这是挺纠结的一个问题,我预想的是在小手机上图片250px应该会很大
为什么并不是我所预料的那样?而且自定义的图片dpi被无视了?----Q2
2.我怀着满心的疑问将图片拷贝到drawable里
实验图片: 250*200,72dpi,res\drawable\wy_250px_200px_72dpi.jpg
实验图片: 250*200,300dpi,res\drawable\wy_250px_200px_300dpi.jpg
貌似对dpi还是免疫,而且OPPO-R15X图片按比例放大了,分别弹了一个 metric.density
,一个3,一个1
哥就想都显示250*200为什么这么难?----Q3
3.怀着疑问,分别将图片在mipmap各个文件夹放一遍
测试结果如下,并画了一张高度变动的简单示意图
可以看出: 1.OPPO-R15X在xxh的时候显示原图,OPPO-R801在m的时候显示原图 2.每种情况下OPPO-R15X的高度总是OPPO-R801的3倍 结论:OPPO-R15X自身dpi(ppi)为402,被圈入了xxh的领域,OPPO-R801自身dpi(ppi)为164,被圈入了m的领域 xxh对应的dpi/m对应的dpi = 3 复制代码
Q1:谁动了我的图片尺寸 ---mipmap的不同文件夹,Android会区分对待 Q2:而且自定义的图片dpi被无视了? ----图片自身的dpi对屏幕设备的显示并没有效果,只对打印有影响 Q3:哥就想都显示250*200为什么这么难? ---- 难! 但是也没有这个必要,你非怎么想,在所有的mipmap文件夹都放一张图, 然后所有手机会显示250*200,不过有人打你不关我事... 复制代码
4.获取不在mipmap里的图片会怎么样?
这个问题问的好,代码测试走一波
不出所料,从文件读取的图片,没走mipmap,所以原像素显示
总结:mipmap会根据图片的文件夹位置对图片在不同density设备上进行不同的缩放,也就是"自动适配"
只限获取图片时或使用时warp_content
三、看看那些尺寸
1.dp:
想必大家这个方法都用过
protected float dp(float dp) { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()); } 复制代码
来看看它到底干了什么:applyDimension
public static float applyDimension(int unit, float value,DisplayMetrics metrics){ switch (unit) { case COMPLEX_UNIT_PX: return value; case COMPLEX_UNIT_DIP: return value * metrics.density;//将值*density返回 case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; } 复制代码
代码追踪:
--> getResources().getDisplayMetrics() -->[android.content.res.Resources#getDisplayMetrics] public DisplayMetrics getDisplayMetrics() { return mResourcesImpl.getDisplayMetrics(); } -->[android.content.res.ResourcesImpl#getDisplayMetrics] DisplayMetrics getDisplayMetrics() { if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels + "x" + mMetrics.heightPixels + " " + mMetrics.density); return mMetrics; } -->[现在要看: mMetrics.density被赋值时] if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) { mMetrics.densityDpi = mConfiguration.densityDpi; mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; } 搜索到:mConfiguration.densityDpi = DisplayMetrics.DENSITY_DEVICE; 复制代码
我们被奉为灵丹妙药的dp只不过获取了 DisplayMetrics.DENSITY_DEVICE
,再乘以0.00625(即除以160)
而且这个 DisplayMetrics.DENSITY_DEVICE
也并非屏幕真正的dpi(ppi),400的,402的都算是480,
所以dp的计算方式也是一个满足大众需要的约值,虽然有一定的效果,但并不能完美适配。
真的有完美的适配吗?
除非你能让 长宽是100*180的纸片
能够恰好装满 长宽是100*200盒子
而且没有变形
或者让所有的安卓手机厂家生产相同比例的手机,否则无论怎么配会有瑕疵,
鱼和熊掌不可兼得
,但 舍生和取义之间还有平常地活着
(尽管并不完美)
我曾经有想过,为什么手机不是圆形的,如果是圆形的就不需要适配了,永远等比例 也许兜里放着占地方吧,或者看电影,可用面积会比较少...感觉好可惜 复制代码
文字单位:sp
-->[android.util.TypedValue#applyDimension] case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; -->[android.content.res.ResourcesImpl#updateConfiguration] mMetrics.scaledDensity = mMetrics.density * (mConfiguration.fontScale != 0 ? mConfiguration.fontScale : 1.0f); //现在焦点移到:mConfiguration.fontScale != 0 //如果是假的,那就和mMetrics.density的值相同,否则是mConfiguration.fontScale 复制代码
其中configuration.fontScale是根据系统字号改变的,默认是1,所以会遇到dp和sp混用无影响的情况。但,一旦用户改变了系统字号,有一定的缩放量,dp的为sp就原形毕露了,所以字体还是乖乖用sp,别没事找事。
关于适配
个人觉得只要多用控件之间进行尺寸依赖关联,也就是约束布局
dp虽然不是灵丹妙药,但是也能治病救人,所以药不能停,dp不能丢
match_parent是好东西,要懂得合理运用
注意左侧和下侧,尽量用父去约束,不然跑出去了……可是大忌 尽量避免使用非常大的dp(200+),可通过控件间相对位置将过大的dp约束,因为数值越大不同手机的差异性越明显。
后记:捷文规范
1.本文成长记录及勘误表
项目源码 | 日期 | 备注 |
---|---|---|
V0.1--github | 2018-12-4 | 理一理屏幕尺寸那些事 |
2.更多关于我
笔名 | 微信 | 爱好 | |
---|---|---|---|
张风捷特烈 | 1981462002 | zdl1994328 | 语言 |
我的github | 我的简书 | 我的掘金 | 个人网站 |
3.声明
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- flutter 屏幕尺寸适配 字体大小适配
- Flutter之支持不同的屏幕尺寸和方向
- 手机屏幕尺寸测试――手机的实际显示页面的宽度
- XBOOT尺寸裁剪
- CSS中的尺寸单位
- iphone – UIBarButtonItem尺寸不同
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript Patterns
Stoyan Stefanov / O'Reilly Media, Inc. / 2010-09-21 / USD 29.99
What's the best approach for developing an application with JavaScript? This book helps you answer that question with numerous JavaScript coding patterns and best practices. If you're an experienced d......一起来看看 《JavaScript Patterns》 这本书的介绍吧!