1. 图片最终的显示还是像素,在像素的基础上google整理出来一套规范,dip(dp)和像素无关性,dip和px的换算公式是 px = density * dip(dp),dip(dp)是在xml布局中确定的。
2. Density对应的是密度,是一个比例值,计算公式:density = dpi / 160 像素/英寸,160像素/英寸是android定义的一个标准(计算规范),至于原因是当前的主流是120,160,240,320,480,对应的密度是0.75 1 1.5 2 3 正好存在整除关系,要用其他做标准不存在整除关系,精确度低。
3. Dpi(每英寸像素个数,可以称作像素密度),常见的是120,240,320,480等等,代表的是屏幕对角线每英寸的像素个数,计算公式涉及到分辨率所以先参考了解分辨率,dpi的计算公式是:设分辨率是长度为a,宽度为b,计算对角线上像素个数是c=√a*a +b*b,dpi=c/屏幕的英寸。
比如那手机华为G660为例:分辨率是1280*720,,5英寸的屏幕根据标准切换成厘米是5英寸=12.5厘米,根据勾股定理计算出来的屏幕宽高是高是10.16厘米,宽是7.62厘米,由上面可以计算出对角线上的像素个数是1468,dpi(每英寸的像素个数)是接近294,android在计算的时候是约数计算,目前只有120到480几个标准(此处是猜测的,有知道详情的望告知),实测此款手机系统打印出来的dpi是320.
备注:手机展示图片的精细程度和dpi有关,同等尺寸,dpi越高,展示的精细程度越高,即同等尺寸分辨率越高,展示的精细程度越高。
400块钱的大屏手机就好嘛?400元的手机一大卖点就是大屏,真正好么?此手机的常见分辨率是960*540 960*640 480*800;屏幕尺寸是5.5寸或者5寸,此处举例分析5寸的上述三种分辨率的dpi及其展示图像的精细程度:上述三种对应的dpi是:1101.45,1153.8,933那么5寸平对应的dpi是220,231,187,由此可见,低于标准240,第三种可以说是远低于,对于图像的展示效果并不好。此种分辨率对应4寸到4.7的还好,高于4.7寸显示效果就不好了,5寸的屏至少的1280*720效果才好一些
4. 分辨率:分辨率是图片或者屏幕的长宽像素的个数,比如当前常见的是1280*720,既是长度上的像素个数是1280,宽度上的像素个数是720,其他的分辨率也是如此。
5. 屏幕尺寸:说的屏幕尺寸值得是屏幕的对角线,多用英寸。1 英寸= 2.539999918 厘米,5英寸接近于12.6厘米
6. 宽高比例:即常说的宽和高比,常见的16:9,4:3等
以上是关于手机和图片的几个专业术语及其信息整理。
二.View在手机屏幕上的宽和高绘制。
1. 对于android,在xml上布局通常使用dip(dp和设备无关性),由上可知:px= density*dp,density = dpi/160,dpi是和分辨率有关的,对于android,dpi通常对应着120,160,240,320,480,(通常手机的dpi达不到标准)由于android的默认标准是160,所以对于dpi = 160的手机,px和dp是1:1的比例,对于dpi=120的手机,px = 0.75dp,在手机上实际的长宽是设置的0.75倍,同理,对于dpi = 240的手机,px = 1.5dp,view的真实尺寸是设置的1.5,dpi=320的是2倍,dpi=480的是3倍,综上可知,大于160的真实尺寸会拉伸,小于160的真实尺寸会缩小。
2. 由于android手机繁多,而且手机厂商由于追求美观,大屏等等原因,手机的真实dpi并不符合android指定的标准,相对于相应的标准dpi,通常会小于。
三.适配的原理:
1. 对于图片,系统有五个文件夹:drawable-xxhdpi ,drawable-xhdpi,drawable-hdpi,drawable-mdpi,drawable-ldpi对应的dpi依次是480,320,240,160,120.对应的比例是:12:8:6:4:3,所以在切图的时候,针对当前最主流的dpi做一套设计,然后切图,再根据上面说到的比例多做其他的4套图放到其对应的文件夹中。比如:当前最主流的分辨率是1280*720,多数对应的是320的dpi(按照标准是这个,不过大东莞无所不能啊),所以设计图可以按照1280*720设计,对于一个长宽为40dip*60dip的view切一个图标为80*120(由于dpi=320和标准是2:1的关系)的icon放到drawable-xhdpi里面,同时需要120*150,60*90,40*60,30*45分别放到drawable-xxhdpi ,drawable-hdpi,drawable-mdpi,drawable-ldpi这样能够精确的保证View的物理尺寸不变而且图片不会被拉伸和缩小。
2.由二中的2可知,手机的真实dpi接近于相应的标准但是略小于,以华为G660为例,真实dpi是294,接近于320,android系统识别的是320,于1同样大小的长度和高度(40dpi*60dpi),按照320计算,其真实的长度是80px*120Px,在华为上的实际长度是73.5 * 110.25,由于view’的width和height是int的所以是73*110,加载图片是80*120,图片会缩小显示,图片的比例是0.666666,view’的宽高比是0.6636636,view宽高比近视接近图片的比例,缩小失真不大,对于那些奇葩dpi(奇葩分辨率和奇葩屏幕尺寸)来说就不好说了。
3. 对于图标图片来说,1的适配方案是相对精确的,但是存在一大弊端是,图片需要做5套,未来在增加的话还需要增加相应分辨率的图片,对于设计来说是灾难啊,有一个相应的替换方案就是制作切图的时候,制作最大dpi(480)对应的分辨率图片,放到drawable里面,没有必要drawable-xhdpi等包中都放一份(减少打包大小)。此种方案对应480dpi的时候不会缩放,对于其他的dpi时,都会缩小,但是对于图片来说,缩小比拉伸失真更小,减少一点精确度,能够减少不小的工作量,而且包的大小也会相应的减小。个别的可以再按照1的方案适配。
4. 系统在解析图片的时候,图片的dpi必须要小于手机的dpi,不然系统无法解析并展示图片。
5. view的绘制是和dpi相关的,而dpi是由分辨率和屏幕尺寸决定的,不同的分辨率和屏幕尺寸组合后的dpi可以相同的,这样就出现了问题,比如我有两个手机,一个是480*800分辨率和4.3寸屏dpi是240,还有一个手机是320*480,尺寸是3.5寸dpi也是240,此时对于一个设定dip的view来说就出问题了,还是说那个面40dp*60dp的view,在240的对应像素是60px*90px,那这样问题就来了,宽为480px,view的宽是60,宽为320px,view的宽也是60,整体UI出现混乱了,我想到的办法是在xml布局文件中不是直接写死40dp和60dp,而是写dimens文件,可以定义不同分辨率和不同分辨率密度下的宽和高,同时android系统也可以分辨率的模式设置文件夹,即drawable-1280x720,value-1280x720等等,在系统加载的时候会根据分辨率优先加载,此时的便利顺序应该是drawable-1280x720----drawable-xhdpi-----drawable。如果对于背景类的view设置了动态的width和height,也要必须同时创建相应分辨率的drawable,放入与其宽高相应的背景图片。
6. 还有一种方式,google都不建议使用的在此描述,不过多了解:
android3.2以后,为了提供更精准的对布局文件的控制,可以通过为资源文件(res目录下文件)增加后缀来指定该文件夹里的xml布局文件或color.xml,string.xml是为哪种大小的屏幕使用。
第一种后缀:swdp,如layout-sw600dp,values-sw600dp
这里的sw代表smallwidth的意思,当你所有屏幕的最小宽度都大于600dp时,屏幕就会自动到带sw600dp后缀的资源文件里去寻找相关资源文件,这里的最小宽度是指屏幕宽高的较小值,每个屏幕都是固定的,不会随着屏幕横向纵向改变而改变。
第二种后缀wdp 如layout-w600dp,values-w600dp
带这样后缀的资源文件的资源文件制定了屏幕宽度的大于Ndp的情况下使用该资源文件,但它和swdp不同的是,当屏幕横向纵向切换时,屏幕的宽度是变化的,以变化后的宽度来与N相比,看是否使用此资源文件下的资源。
第三种后缀hdp 如layout-h600dp,values-h600dp
这个后缀的使用方式和wdp一样,随着屏幕横纵向的变化,屏幕高度也会变化,根据变化后的高度值来判断是否使用hdp ,但这种方式很少使用,因为屏幕在纵向上通常能够滚动导致长度变化,不像宽度那样基本固定,因为这个方法灵活性不是很好,google官方文档建议尽量少使用这种方式。摘自点击打开链接
综上可知,图片的加载和分辨率有关,也和dpi有关,具体看当前view是怎么处理的,如果是在xxhdpi,xhdpi,hdpi,mdpi,ldpi或者在xml直接写死宽和高,系统的图片加载取决于前面四个文件夹,如果通过dimens文件设置了不同分辨率,就和分辨率有关了。两种用法最好不要混合使用,混合的话就是按照顺序(drawable-1280x720----drawable-xhdpi-----drawable)执行了,效果更不好(总之android的适配就是坑啊)。
参考:
特别感谢以上作者,让我对android适配有了更深层次的了解