一、适配原理
1.分辨率
320*480(分辨率) - 160(dpi) - 1.0 (density) - mdpi (drawable) - 48*48 (应用icon) - 320dp (宽)
480*800 (分辨率) - 240(dpi) - 1.5(density) - hdpi (drawable) - 72 * 72 (应用icon) - 320dp (宽)
720|768*1280(分辨率) - 320(dpi) - 2(density) - xhdpi (drawable) - 96 * 96 (应用icon) - 360|384dp (宽)
1080*1920(分辨率) - 480(dpi) - 3(density) - xxhdpi (drawable) - 144 * 144 (应用icon) - 360dp (宽)
1440*2560(分辨率) - 640(dpi)- 4(density) - xxxhdpi (drawable) - 192 * 192 (应用icon) - 360dp (宽)
换算公式:例如手机分辨率是320p(720 * 1280),density->320/160 = 2,drawable对应xhdpi,icon 48*2 = 96。
目前系统支持分辨率一共有 ldpi(0.75) 、 mdpi(1) 、hdpi(1.5)、x-hdpi(2)、xx-hdpi(3)、xxx-hdpi (4)6大类。
参考:屏幕密度等级和屏幕逻辑尺寸表:https://blog.csdn.net/zhaoyw2008/article/details/46008513
公式
px = density * dp;
density = dpi / 160;
px = dp * (dpi / 160);
2.用ios设计图的原因
目前市场上IOS设备的尺寸基本上是以下几种:
5/5C/5S:320x480pt 640X1136px
6/6S/7/7S:375x667pt 640X1136px
6 Plus / 6S Plus / 7 Plus / 7S Plus:414x736pt 1242X2208px
X:375x812pt 1125X2436px
目前设计大部分是按ios6-7分辨率(750 * 1334)
目前手机端主流分辨率是16:9,都是按宽去做相应拉伸。
以ios7的dpi 是 326 。图片对应 - xhdpi dp对应375。
安卓端宽dp 在 320 ~ 411之间 因此分辨率低的手机上控件有缩的效果,分辨率高有细微放大效果
参考
Ios设计标准:https://www.jianshu.com/p/01768b59bbe1
android设计标准:https://blog.csdn.net/qq_21937107/article/details/80151080
3.系统查找图片从离当前手机分辨率最高密度drawable文件开始查找
eg: 假设将图片只放入ldpi ,当前手机分辨率是720p(x-hpdi)。 系统在x-hdpi目录下没找到图片,会从xx-dpi下找。查找顺序(x-hdpi -> xx-hdpi -> xxx-hdpi -> hdpi -> mdpi -> ldpi)
4.bitMap占用内存大小
在对手机进行屏幕适时,可以只切一套图适配所有的手机。
1>如果只切一套小图,那在高屏幕密度手机上,会对图片进行放大,这样图片占用的内存往往比切相应图片放在高密度文件夹下,占用的内存还要大。但是只切一套大图放在高幕文件夹下,在小屏幕密度手机上,会缩小显示,按道理是行得通的。但系统在对图片进行缩放时,会进行大量计算,会对手机的性能有一定的影响。同时如果图片缩放比较狠,可能导致图片出现抖动或是毛边。
所以最好切出不同比例的图片放在不同幕度的文件夹下,对于性能要求不大高的图片,可以只切一套大图;
2>一张图片占用内存=图片长 * 图片宽 / (资源图片文件密度/手机屏幕密度)^2 * 每一象素占用字节数,所以图片占用内存跟图片本身大小、手机屏幕密度、图片所在的文件夹密度,图片编码的色彩格式有关;
3>对于网络图片,在不同屏幕密度的手机上加载出来,占用内存是一样的。
4>对于网络或是assets/手机本地图片加载,如果想通过设置Options里的
inDensity或是inTargetDensity参数来调整图片的缩放比,必须两个参数均设置才能起作用,只设置一个,不会起作用。
5.drawable和minmap区别
1>在App中,无论你将图片放在drawable还是mipmap目录,系统只会加载对应density中的图片。
2>而在Launcher中,如果使用mipmap,那么Launcher会自动加载更加合适的密度的资源。
3>应用内使用到的图片资源,并不会因为你放在mipmap或者drawable目录而产生差异。单纯只是资源路径的差异R.drawable.xxx或者R.mipmap.xxx。(也可能在低版本系统中有差异)
一句话来说就是,自动跨设备密度展示的能力是launcher的,而不是mipmap的。
二、界面适配方案
1.宽高限定符适配 (多套DIMEN-480*320)
缺点:
1.需要”精确命中”,容错机制很差。当不存在对应分辨率的文件时 会去默认的dimen文件中读取
2.smallestWidth适配(多套DIMEN -sw320dp)
smallestWidth适配,或者叫sw限定符适配。指的是Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),然后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。
3.UI适配框架(AutoLayout)
https://github.com/hongyangAndroid/AndroidAutoLayout (已停止更新)
第一步:在你的项目的AndroidManifest中注明你的设计稿的尺寸
<meta-data android:name="design_width" android:value="768">
</meta-data>
<meta-data android:name="design_height" android:value="1280">
</meta-data>
第二步:让你的Activity继承自AutoLayoutActivity.
缺点:
1.框架要在运行时会在onMeasure里面做变换,我们自定义的控件可能会被影响或限制,可能有些特定的控件,需要单独适配,这里面可能存在的暗坑是不可预见的
2.整个适配工作是有框架完成的,而不是系统完成的,一旦使用这个框架,未来一旦遇到很难解决的问题,替换起来是非常麻烦的,而且项目一旦停止维护,后续的升级就只能靠你自己了,这种代价团队能否承受
4.百分比布局
已废弃~
5.头条方案
根据设计宽度 修改目标设备的density
1.修改Activity和Application的Density.
2.做字体适配工作
参照
https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA
https://github.com/jarryleo/MagicScreenAdapter
各方案对比:https://blog.csdn.net/yang1349day/article/details/80754917