关于Android中drawable必知的一些规则
前言
一入Android深似海,相信很多Android开发者深有体会,Android系统版本的碎片化,Android硬件设备的多样性,第三方Rom的不确定因素。现在想开发一个合格的商业化App真的不容易,先不说别的,应用的兼容性就是一项技术和耐心的双重考验,想完美适配各种情况可以说是不可能的,往往都是在人力和适配率之间寻找平衡,今天要说的drawable就是需要适配的一个重要角色。
配置限定符
对于不同的屏幕密度、不同的设备方向,不同的语言和区域,都会涉及到备选drawable资源,在运行时,Android会检测当前设备配置并根据具体规则(后面会提到)为应用加载合适的资源。下面是可以使用的配置限定符,需要说明的是这些配置限定符不仅对drawable有效,对其他资源类型(如:layout等)也有效:
移动国家代码(MCC):mcc310,mcc310-mnc004,mcc208-mnc00
语言和区域:en,fr,en-rUS等等
布局方向:ldrtl(从右到左)ldltr(从左到右)
smallestWidth:sw<N>dp如:sw320dp,sw600dp,sw720dp等等,屏幕可用高度和宽度的最小尺寸,屏幕的“最小可能尺寸”。
可用宽度:w<N>dp如:w720dp,w1024dp等等,指定资源应该使用的最小可用屏幕宽度,以dp为单位,由<N>值定义。在横向和纵向之间切换时,为了匹配当前实际宽度,此配置值也会随之发生变化。
可用高度:h<N>dp如:h720dp,h1024dp等等,指定资源应该使用的最小可用屏幕高度,以dp为单位,由<N>值定义。在横向和纵向之间切换时,为了匹配当前实际高度,此配置值也会随之发生变化。
屏幕尺寸:small,normal,large,xlarge
屏幕纵横比:long宽屏,如WQVGA、WVGA、FWVGA;notlong非宽屏,如QVGA、HVGA和VGA
屏幕方向:port设备处于纵向(垂直),land设备处于横向(水平)
UI模式:car,desk,television,appliance,watch
夜间模式:night夜间,nontight白天
屏幕像素密度:ldpi,mdpi,hdpi,xhdpi,xxhdpi,xxxhdpi,nodpi,tvdpi
触摸屏类型:notouch,finger
键盘可用性:keysexposed,keyshidden,keyssoft
主要文本输入法:nokeys,qwerty,12key
导航键可用性:navexposed导航键可供用户使用,navhidden导航键不可用
主要非触摸导航方法:nonav,dpad,trackball,wheel
平台版本(API级别):v3,v4,v7等等,如v1对应于API级别1,v4对应于API级别4
如果你认真研究下每个配置限定符,你就会体会到:想完美适配各种情况可以说是不可能的,其实我们平时最常用的也是基本必须要用的就是屏幕像素密度,这里有必要详细的说一下该参数:
ldpi:低密度屏幕;约为120dpi。
mdpi:中等密度(传统HVGA)屏幕;约为160dpi。
hdpi:高密度屏幕;约为240dpi。
xhdpi:超高密度屏幕;约为320dpi。API级别8中新增配置
xxhdpi:超超高密度屏幕;约为480dpi。API级别16中新增配置
xxxhdpi:超超超高密度屏幕使用(仅限启动器图标,请参阅“支持多个屏幕”中的注释);约为640dpi。API级别18中新增配置
nodpi:它可用于您不希望缩放以匹配设备密度的位图资源。
tvdpi:密度介于mdpi和hdpi之间的屏幕;约为213dpi。它并不是“主要”密度组,主要用于电视,而大多数应用都不需要它。对于大多数应用而言,提供mdpi和hdpi资源便已足够,系统将根据需要对其进行缩放。API级别13中引入了此限定符。
六个主要密度之间的缩放比为3:4:6:8:12:16(忽略tvdpi密度)。因此,9x9(ldpi)位图相当于12x12(mdpi)、18x18(hdpi)、24x24(xhdpi)位图,依此类推。
限定符命名规则
可以为单组资源指定多个限定符,并使用短划线分隔。例如,drawable-en-rUS-land适用于横排美国英语设备。
这些限定符必须遵循上面列出的顺序,所以上面的列表是有顺序的。例如:错误:drawable-hdpi-port/,正确:drawable-port-hdpi/
不能嵌套备用资源目录。例如,您不能拥有res/drawable/drawable-en/。
值不区分大小写。在处理之前,资源编译器会将目录名称转换为小写,以避免不区分大小写的文件系统出现问题。名称中使用的任何大写字母只是为了便于认读。
对于每种限定符类型,仅支持一个值。例如,若要对西班牙语和法语使用相同的drawable文件,则您肯定不能拥有名为drawable-rES-rFR/的目录,而是需要两个包含相应文件的资源目录。
Android匹配最佳drawable规则
如果你只使用一个配置限定符,那么很好匹配,找到符合该配置的drawable即可,但当你同时使用多个配置限定符,且同时存在多个drawable目录时,匹配最佳drawable就没那么简单了,这里以AndroidDeveloper官方的例子说明,例如:现在你的应用包含如下目录:
drawable/ drawable-en/ drawable-fr-rCA/ drawable-en-port/ drawable-en-notouch-12key/ drawable-port-ldpi/ drawable-port-notouch-12key/
同时,假设目标设备的配置如下:
区域设置=en-GB 屏幕方向=port 屏幕像素密度=hdpi 触摸屏类型=notouch 主要文本输入法=12key
具体的匹配过程如下:
1、淘汰与设备配置冲突的资源文件:其中drawable-fr-rCA/目录与en-GB区域设置冲突,因而被淘汰(但有个例外,屏幕像素密度是唯一一个未因冲突而被淘汰的限定符,尽管设备的屏幕密度为hdpi,但是drawable-port-ldpi/未被淘汰,因为此时每个屏幕密度均视为匹配)
2、选择在上面限定符列表中优先级最高的限定符,先从MCC开始,然后下移,看是否有资源目录包括此限定符,若无则看下一个限定符,在该示例中,除非达到语言限定符,否则答案始终为“否”。
3、若有,则淘汰不含此限定符的资源目录。在该示例中,系统会淘汰所有不含语言限定符的目录。所以到这一步符合要求的drawable还剩:
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
4、选择下一个优先级的限定符,重复执行步骤2,3,4。直到只剩下一个目录,该例中应该是port,所以淘汰后只剩:
drawable-en-port/
有两点需要说明一下:
1、屏幕像素密度是唯一一个未因冲突而被淘汰的限定符,如果涉及的限定符是屏幕像素密度,则Android会选择最接近设备屏幕密度的选项。通常Android倾向于缩小大型原始图像,而不是放大小型原始图像。
2、如果一个符合限定符的drawable都没有怎么办?还能怎么办,崩溃呗!
drawable和mipmap的区别和联系
现在通过AndroidStudio创建工程,默认会创建一系列mipmap文件夹,而不是以前的drawable文件夹。那么mipmap和drawable到底是什么关系?mipmap取代了drawable了吗?先看一下官方说明:
drawable/
Forbitmapfiles(PNG,JPEG,orGIF),9-Patchimagefiles,andXMLfilesthatdescribeDrawableshapesorDrawableobjectsthatcontainmultiplestates(normal,pressed,orfocused).SeetheDrawableresourcetype.
mipmap/
Forapplaunchericons.TheAndroidsystemretainstheresourcesinthisfolder(anddensity-specificfolderssuchasmipmap-xxxhdpi)regardlessofthescreenresolutionofthedevicewhereyourappisinstalled.Thisbehaviorallowslauncherappstopickthebestresolutioniconforyourapptodisplayonthehomescreen.Formoreinformationaboutusingthemipmapfolders,seeManagingLauncherIconsasmipmapResources.
这里先说结论:mipmap文件夹下,仅仅建议放启动图标(applaunchericons),也就是应用安装后,会显示在桌面的那个图标,而其他的图片资源等,还是按照以前方式,放在drawable文件夹下。
那么为什么要把LauncherIcon放在mipmap文件夹下?下面英文是官方解释:
Differenthomescreenlauncherappsondifferentdevicesshowapplaunchericonsatvariousresolutions.Whenappresourceoptimizationtechniquesremoveresourcesforunusedscreendensities,launchericonscanwinduplookingfuzzybecausethelauncherapphastoupscalealower-resolutioniconfordisplay.Toavoidthesedisplayissues,appsshouldusethemipmap/resourcefoldersforlaunchericons.TheAndroidsystempreservestheseresourcesregardlessofdensitystripping,andensuresthatlauncherappscanpickiconswiththebestresolutionfordisplay.
Makesurelauncherappsshowahigh-resolutioniconforyourappbymovingalldensitiesofyourlaunchericonstodensity-specificres/mipmap/folders(forexampleres/mipmap-mdpi/andres/mipmap-xxxhdpi/).Themipmap/foldersreplacethedrawable/foldersforlaunchericons.Forxxhpdilaunchericons,besuretoaddthehigherresolutionxxxhdpiversionsoftheiconstoenhancethevisualexperienceoftheiconsonhigherresolutiondevices.
这里是我的理解:很多不同的LauncherApp采用的LauncherIcon的大小不一致,而在应用安装时Android资源优化会把drawable文件夹下不需要的分辨率资源删除掉,例如在xhdpi的设备上将drawable-xxhdpi下的资源删掉,当然里面的LauncherIcon也会被删掉,这时如果LauncherApp采用的LauncherIcon大小偏大,而高分辨xxhdpi下的Icon又被删掉了,就只能把xhdpi下的小尺寸Icon进行放大显示了,这样就会造成LauncherIcon显示模糊。为了避免上面的问题,就引入了mipmap,Android会保证mipmap下的资源不会因为资源优化而被删除,确保大尺寸的LauncherIcon可以找到更合适分辨率的Icon。所以mipmap是为LauncherIcon而生的,而其它的图片资源还是放在drawable文件夹下,这样有助于Android资源优化删除无用的资源,减少应用体积。
总结
以上就是关于Android中drawable必知的一些规则的全部内容,文章内容对于Android开发者来说很实用,希望对各位有所帮助。