图片适配
1、切多套图,正确的图片放入正确的文件夹下面
图片适配什么意思?为什么要有图片适配?
首先看一张图
在默认的res文件夹下面,发现有这么多mipmap文件夹,现在看到里面只是放了一个ic_launcher图片,就是应用的启动图标,为什么要有这么多张?
点开之后发现每张图片的分辨率和所占用的大小都不一致
mipmap-mdpi 48x48 2.21k
mipmap-hdpi 72x72 3.42k
mipmap-xhdpi 96x96 4.84k
mipmap-xxhdpi 144x144 7.72k
mipmap-xxxhdpi 192x192 10.49k
这是因为每个手机的屏幕密度都不一样,当程序运行到手机上时,系统会根据当前手机所对应的屏幕密度去找相应文件夹下面的图片。比如当我们启动一个屏幕密度为mdpi的手机时,加载的其实就是分辨率48x48大小为2.21k的ic_launcher图片,其他以此类推。我们需要按照规则将不同的图片放到相对应的文件夹下面,这样做的好处就是节省内存。下面做一个实验来验证这一结论。
首先去找一张1080x1920分辨率的图片,该图片信息如下:
可以看到,这是一张1080x1920分辨率、1.3MB的图片,我们把它放到mipmap-xxhdpi的文件夹下面,接下来启动一个1920x1080分辨率的模拟器。
然后xml布局里将其设置为背景,然后运行。
打开Android Studio的内存检测,检查耗费的内存,如图
可以看到,这个1.3MB的图片运行到这个手机上所消耗的内存是9.53MB。
接下来,咱们把这个图片移动到mipmap-hdpi文件夹下面,等于说还是原来的图片,只是换个文件夹,这样在运行的时候手机会加载mipmap-hdpi这个文件夹下面的图片。运行后,监测内存情况如下:
可以看到,这个1.3MB的图片运行到这个手机上所消耗的内存是32.97MB。
当我们把它放进mipmap-mdpi文件夹下面时,情况如下:
可以看到,这个1.3MB的图片运行到这个手机上所消耗的内存是72.48MB。
为什么都是同一张图片,什么都没改,只是换了个文件夹而已,它就有这么大的区别呢?
这张图片是1.3Mb,我们启动的模拟器参数如下:
屏幕尺寸:4.95英寸
分辨率 :1920x1080
根据前面所讲的屏幕像素密度计算公式可以得出该模拟器的屏幕像素密度是445,这就意味着它对应的xxhdpi,它会优先去加载此文件夹下面的图片。
因此当我们把图片放到xxhdpi文件夹下面时,系统第一优先找的是这个文件夹,这是有好处的,好处就是节省内存,从上图也可以看出,的确如此。这就是为什么我们要在对应的文件夹下面放对应分辨率图片的好处,就是占用内存小。这就是好处,至于为什么会出现这么大的差别,我们这样来分析。
还记得前面讲过,mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi的比例是2:3:4:6:8的概念吗?
当前图片1.3Mb,放到相应文件夹下面时占用内存不同
xxhdpi : 9.53Mb
xhdpi :19.08Mb
hdpi :32.97Mb
mdpi :72.48Mb
首先这张图片理应消耗的内存是9.53Mb-1.3Mb=8.23Mb (在手机里占用的内存-图片自身的大小)
得出该图片大约为8Mb,分析其他几种情况:
当放到mdpi下时,按照2:3:4:6:8的比例,mdpi跟xxhdpi的比例是2:6,我们的模拟器是xxhdpi的,在去mdpi文件夹里找图片时会自动转换,转换的比例就是2:6。也就是1:3的关系,既然如此,宽是3倍,高是3倍,自然一张图就变成了9倍。
所以一张在xxhdpi文件夹下理应占据8Mb的图片跑到mdpi时无形中就变成了8Mbx 9=72Mb,也就是上面的72.48Mb
再分析hdpi的情况,跟xxhdpi的比例是3:6,也就是1:2,2 x 2=4,也就是扩大了4倍。
所以8Mb x 4=32Mb,也符合上面的情况。
xhdpi是4:6,也就是1.5x1.5=2.25
所以8Mb x 2.25 = 18Mb左右,差不多也跟上面一样。
由此可见,一张图片放到正确的文件夹里面是多么的重要,由此你是否明白Google为什么造了那么多套ic_launcher的图片了呢?
2、使用.9图,自动拉伸位图
Android里有9patch图的概念,也就是.9图,能够自动拉伸你指定的地方,这其实是一种格式特殊的png文件,能指明可以拉伸以及不可拉伸的区域,同时还可以把显示内容区域的位置标示清楚。
举个最简单的例子,比如看QQ的聊天框
其实咱们发的文字是内容区域,后面的其实就是个背景图片。
在我们的代码里,比如我们找一张聊天背景的图片,如下
接下来放到我们的xml布局里面,当我给TextView设置了文字,可以看到如下效果:
文字内容不在正中间,即使我们调整文字内容在中间以求得显示正常,如下:
那也要考虑另一个问题,当文字内容特别多的时候的一个显示效果,如图:
这样图片完全变形了,比如内容区域变形了,而且“尖儿”不应该被变大的,那该怎么办呢?
首先这个背景图片要能根据文字内容的排版改变自己的大小,这个毋庸置疑,但是每个聊天框都有一个“尖儿”,这个是要对准发信息的人,我们怎么能保证这个“尖儿”不被拉伸呢?
如果只是一张单纯的图片,在文字内容为一行的时候不会发生什么改变,但是当文字内容超过2行或者更多时,图片肯定就会变形。
那问题是,我们怎么保证图片不会随着文本内容的改变而变形呢?或者说如何让内容区域限定在一个区域范围内呢?
这就要引入了.9图的概念了。
先看一张图:
这是.9图制作的一个入门,首先你要明白这个图片四周的四条黑边的作用。
左边和上边的两条黑线代表的就是拉伸区域,就是我们控制这张图片哪些区域可以缩放,缩放的区域就是两条黑边的交集,即第一张图的紫色区域。
右边和下边代表的是padding,就是间隔区域,通俗来讲就是文本内容的区域,下面给出示例。
如果我们能让内容定死,那就万事大吉,下面介绍.9图的制作。
首先第一步,选中你家UI妹子给的图,右键点击,选中create9-patch file
然后点击ok
然后点开创建好的.9图进入编辑模式
这张图我就不做过多解释了,必要的文字信息都在图上面标注了。可以看到当拉伸的时候图片变形了,尤其是那个“尖儿”。
下面讲讲怎么制作这张图片,或者说怎么设置拉伸区域。
如上面所讲,我先在左边画一条黑线,如图
发现右边的三种视图变化了,由于我画的黑边横向穿过的区域没有涉及到“尖儿”,所以无论怎么拉伸,“尖儿”都不会变形,下面我再在上面画一条。
其实跟上面的没什么太大区别,但是.9图的有两条线必须画,就是左边和上边,否则会报错。
上图的红色区域就是图片会被拉伸的区域,其他地方不会发生任何变化,这个时候,一个简单的.9图就制作完成了。
这个时候再看xml布局的显示效果。
当然,你也可以把剩下的两条边给画上,那是设置内容区域的padding的,我就简明扼要的说一下,这个不是重点。
设置好之后,我们去掉该TextView的padding属性和gravity属性运行到手机上,效果图如下:
多套切图的解决办法
我们需要提供备用位图(符合屏幕尺寸的图片资源)
由于 Android 可在各种屏幕密度的设备上运行,因此我们提供的位图资源应该始终可以满足各类密度的要求:
密度类型 代表的分辨率(px) 系统密度(dpi)
低密度(ldpi) 240x320 120
中密度(mdpi) 320x480 160
高密度(hdpi) 480x800 240
超高密度(xhdpi) 720x1280 320
超超高密度(xxhdpi) 1080x1920 480
根据以下尺寸范围针对各密度生成相应的图片。
比如说,如果我们为 xhdpi 设备生成了 200x200 px尺寸的图片,就应该按照相应比例地为 hdpi、mdpi 和 ldpi 设备分别生成 150x150、100x100 和 75x75 尺寸的图片
即一套分辨率=一套位图资源
接下来将生成的图片文件放在 res/ 下的相应子目录中(mdpi、hdpi、xhdpi、xxhdpi),系统就会根据运行您应用的设备的屏幕密度自动选择合适的图片
最后通过引用 @mipmap/id,系统都能根据相应屏幕的 屏幕密度(dpi)自动选取合适的位图。
注意:
如果是.9图或者是不需要多个分辨率的图片,放在drawable文件夹即可
对应分辨率的图片要正确的放在合适的文件夹,否则会造成图片拉伸等问题。
更好地方案解决“图片资源”适配问题
上述方案是常见的一种方案,这固然是一种解决办法,但缺点很明显:
1.每套分辨率出一套图,为美工或者设计增加了许多工作量
2.对Android工程文件的apk包变的很大
那么,有没有一种方法:
保证屏幕密度适配
可以最小占用设计资源
使得apk包不变大(只使用一套分辨率的图片资源)
下面我们就来介绍这个方法:
只需选择唯一一套分辨率规格的图片资源
Google官方给出的高清设计图尺寸有两种方案,一种是以mdpi设计,然后对应放大得到更高分辨率的图片,另外一种则是以高分辨率作为设计大小,然后按照倍数对应缩小到小分辨率的图片。
推荐使用第二种方法,因为小分辨率在生成高分辨率图片的时候,会出现像素丢失。
而分辨率可以以1280*720或者是1960*1080作为主要分辨率进行设计。
首先来理解下Android 加载资源过程
Android SDK会根据屏幕密度自动选择对应的资源文件进行渲染加载(自动渲染)
比如说,SDK检测到你手机的分辨率是320x480(dpi=160),会优先到mipmap-mdpi文件夹下找对应的图片资源;但假设你只在xhdpi文件夹下有对应的图片资源文件(mdpi文件夹是空的),那么SDK会去xhdpi文件夹找到相应的图片资源文件,然后将原有大像素的图片自动缩放成小像素的图片,于是大像素的图片照样可以在小像素分辨率的手机上正常显示。
所以理论上来说只需要提供一种分辨率规格的图片资源就可以了。
那么应该提供哪种分辨率规格呢?
如果只提供ldpi规格的图片,对于大分辨率(xdpi、xxdpi)的手机如果把图片放大就会不清晰
所以需要提供一套你需要支持的最大dpi分辨率规格的图片资源,这样即使用户的手机分辨率很小,这样图片缩小依然很清晰。
xhdpi应该是首选
原因如下:
xhdpi分辨率以内的手机需求量最旺盛
目前市面上最普遍的手机的分辨率还多集中在720X1080范围内(xhdpi),所以目前来看xhdpi规格的图片资源成为了首选。
而且很多公司为了保持App不同版本的体验交互一致,可能会以iPhone手机为基础进行设计,包括后期的切图之类的。
iPhone主流的屏幕dpi约等于320, 刚好属于xhdpi,所以选择xhdpi作为唯一一套dpi图片资源,可以让设计师不用专门为Android端切图,直接把iPhone的那一套切好的图片资源放入mipmap-xhdpi文件夹里就好,这样大大减少的设计师的工作量!
点此进入:Android 人事+技术总贴
点此进入:Android 基础篇总贴
点此进入:Android 进阶篇总贴
点此进入:Android 讨论区
以上言论,如有错误或者表达不准确或者有纰漏的地方还请指正,同时欢迎大家在评论区留言给予一定的建议,我会根据大家的意见进行相应的改正,谢谢各位!