android市场上的手机尺寸有大有小,分辨率各有不同,怎么去适配这上千种屏幕类型呢,androidStudio采用新建不同分辨率的文件夹放置对应的图片,在适配时,虚拟机会根据运行手机的手机分辨率密度查找对应的文件夹的图片,从而解决问题,在studio中新建项目时系统会自动帮你建好mipmap各种分辨率文件夹,在project目录下可以看到,这mipmap中注意放置的是图标,因为系统对图标要进行特殊的优化,如果要放置其他的图片资源文件,开发者必须要自己新建drawable-xhdpi,drawable-xxhdpi等,那么在每个drawable对应多大的dpi呢,看下图
可以看到不同的密度对应不同的dpi,那怎么算手机的dpi,有两种方法,一种是代码的形式
float xdpi=getResourse().getDisplayMetrics().xdpi; floa ydpi=getResourse().getDisplayMetrics().ydpi;
算出的xdpi和ydpi大体上是相等的,即为屏幕dpi,还有一种是数学算法:
x代表是手机宽度的分辨率,如720p,y代表高度分辨率,如1280p,屏幕尺寸一般上手机上都有标注,如4.7寸,那么根据上面的公司可以算出屏幕分辨率,这种方法算出的结果和上面也是差不多的。
那么我们现在来讨论下,如果一张图片本来是在xhdpi里面的,误放入mdpi是会怎么样,现在将一张270*480px的图片放在真机上调试
真机屏幕是720*1280的分辨率,算出dpi是320,对应表中属于xhdpi文件夹,调试拿到宽度和高度和原始尺寸一样270高度480,现在将这张图片移入xxhdpi文件夹里,显示图片大小是180,320,变小了,接着再将这张图片移入mdpi中,显示宽高是540和960,怎么又变大了,
android系统取图片的机制:
android系统再取图片时,会先算出手机的dpi,根据dpi的值到对应范围的drawable文件夹中取图片,如果这个文件夹有这张图片,则正常显示图片的尺寸,如果对应文件夹没有这张图片,就会去更高分辨率drawable文件夹取图片,如果有的话就显示,这时显示的图片会变小,因为系统会认为这张图是为更高分辨率手机设置的,如果正常显示会很大,所以可以的缩小了,缩小的倍数刚好是对应dpi范围最大值之间的倍数,如上测试的倍数是320/480,缩小2/3倍,如果更高分辨率文件夹还是没有这张图片,就会去drawable-nodpi文件夹找,这个文件夹默认是不会缩放图片的,有多大就显示多大,如果还是没有,就往低分辨率文件夹找,这时图片会放大,如测试这张图片放大倍数960/480,放大了2倍,这也意味着占更大的内存空间,因此,尽量匹配高分辨率图片,节省内存,现在市场上基本上是xhdpi和xxhdpi手机居多,可以配这两种类型手机图片就行。
2017.07.12更新:
一张458px*856px的图片,色彩格式为ARGB_8888,放在屏幕密度为160dpi的手机上调试,放在不同文件夹下占用内存大小如下:
文件夹 | 文件夹密度 | 屏幕密度 | 占用内存大小 | 屏幕密度/文件夹密度 |
---|---|---|---|---|
drawable-ldpi | 120dpi | 160dpi | 2.98M | 2 |
drawable/drawable-mdpi | 160dpi(匹配) | 160dpi | 1.49M | 1 |
drawable-hdpi | 240dpi | 160dpi | 680k | 约1/2 |
drawable-xhdpi | 320dpi | 160dpi | 382k | 1/4 |
drawable-xxhdpi | 480dpi | 160dpi | 170k | 1/8 |
drawable-xxxhdpi | 640dpi | 160dpi | 96k | 1/16 |
由此可以得出结论:
1、如果能找到与自己屏幕密度相等的文件夹密度的图片,则占用内存为图片高乘以图片宽乘以色彩占用字节数.
2、如果相应文件夹找不到,系统会向高密度文件夹下查找,如果能找到图片,会缩小图片,内存也会缩小相应倍数的平方。
3,如果向上也找不到,则会向下查找,若能找到图片,会放大图片,内存会增大相应倍数的平方
图片占用内存公式:
占用内存=图片宽度X图片高度X(1/2)^(文件夹密度/屏幕密度)X色彩格式占用字节数
电脑占用的是存储内存,这里计算的是运行内存,要区别开来
如果加载sd卡图片或者assets图片或者网络图片,都是将图片转为数据流格式,如果不设置options,则图片占用内存都是一样的,跟手机屏幕密度无关,如果要进行压缩,可以设置options中的俩个参数,
options.inDensity:图片本身的像素密度,看再哪个文件夹下,再assets、sd卡、网络中都是默认160.
options.inTargetDensity:图片最终在bitmap中的像素密度,如果没有赋值,则默认设置成inScreenDensity
options.inScreenDensity:手机本身的屏幕密度,如果inDensity和inTargetDensity不相等,则要对图片进行缩放,inScale=inTargetDensity/inDensity。
要同时设置inDensity和inTargetDensity两个值,才有效果。