Android屏幕适配解析-详解像素,设备独立像素,归一化密度,精确密度及各种资源对应的尺寸密度分辨率适配问题最近遇到了一系列的屏幕适配问题,以及屏幕画图像素密度相关的问题,索性在这里全部总结下;1.名词解析在之前写过的AndroidUI设计之布局管理器-详细解析布局实现中的第七小节已经说明了一部分;(1)通用名词屏幕尺寸(screensize):按照屏幕的对角线测量的实际大小;--屏幕尺寸分类:屏幕尺寸分为小(small),普通(normal),大(large),超大(extralarge)四种;--自动渲染:AndroidSDK根据屏幕实际尺寸,选择一种方式(四选一)对布局进行渲染,这是人为不可控的,对程序员透明;屏幕尺寸界线:屏幕的尺寸是按照dp计算的,dp越大,尺寸越大;--small(小屏):最少320dp*426dp;--normal(普通):最少320dp*470dp;--large(大屏):最少480dp*640dp;--xlarge(超大):最少720dp*960dp;屏幕长宽比(aspectratio):手机屏幕物理宽度和物理高度比例关系,程序中可以为指定长宽比屏幕提供布局资源;屏幕分辨率(resolution):屏幕上显示的物理像素总和,如320*480;--注意:分辨率不等于屏幕宽高比,在Android程序中尽量避免直接使用px;像素(px):实际的分辨率,例如在320*480分辨率手机上,320和480就是像素点;分辨率(px)与设备独立像素(dip)比较:dip越大,屏幕的尺寸越大,分辨率越高,越清晰,屏幕大分辨率不一定大,如电脑;(2)Android设备相关名词密度(density):在物理宽高范围内显示的像素数量,同样屏幕大小的手机,低密度显示的像素点少,高密度显示的像素点多;--资源分类:固定像素宽高的UI资源(图片资源的宽高是按照像素确定的),在低密度显得很大,在高密度显示的很小,因此为了使UI组件显示大致统一(不是绝对),美工需要一种资源设置成4份不同像素的资源,放到对应目录中去;设备独立像素(dip/dp):该像素与设备硬件有关,不同的设备显示效果不同,与实际密度和像素无关;--密度(dpi)无关:密度是每英寸包含像素个数,dip是基于屏幕物理密度的抽象单位;--dip与px等效情况:在密度为160dip的屏幕上,1dip==1px,320*480分辨率手机宽2英寸高3英寸,那么手机密度为160dpi;--屏幕不变分辨率改变:如果上面2*3英寸屏幕不变,分辨率改成480*800分辨率,这时每英寸的像素数量明显增加了,即密度增加,为240dpi,2英寸有480像素;屏幕不变的前提下,如果在160pi下100dip像素的实际长度与240dip下100dip像素的实际长度是一样的;--实际尺寸计算:view组件使用dip作为单位,如果在160dpi下直接按照像素点画出,如果密度不是160dpi,那么会计算一个转换比例,这个比例与实际尺寸相乘得到新的像素点个数;--计算公式:px=dip*density/160;当密度为160的时候,屏幕的px==dip;--Google建议:在布局文件设置组件属性的时候,尽量使用dip作为单位,字体大小统一使用sp作为单位;px与dip区别:下面的情况是以屏幕尺寸不变为前提的;--px绘图:在320像素宽的手机上,100px的长度是480宽度像素手机上长度的2/3;--dip绘图:屏幕大小不变的情况下,100dip在320480像素手机上实际尺寸长度是一样的;px与dip,px与sp之间转化工具类:publicclassDisplayUtils{publicstaticintpx2dip(floatpxValue,floatscale){return(int)(pxValue/scale+0.5f);}publicstaticintdip2px(floatdipValue,floatscale){return(int)(dipValue*scale+0.5f);}publicstaticintpx2sp(floatpxValue,floatfontScale){return(int)(pxValue/fontScale+0.5f);}publicstaticintsp2px(floatspValue,floatfontScale){return(int)(spValue*fontScale+0.5f);}}.(3)获取密度相关方法示例注意:区分屏幕密度和单个方向精确密度;packageshuliang.han.displaytest;importandroid.app.Activity;importandroid.os.Bundle;importandroid.util.DisplayMetrics;publicclassMainActivityextendsActivity{//屏幕的宽高,单位像素privateintscreenWidth;privateintscreenHeight;//屏幕的密度privatefloatdensity;//只有四种情况:0.75/1.0/1.5/2.0privateintdensityDpi;//只有四种情况:120/160/240/320//水平垂直精确密度privatefloatxdpi;//水平方向上的准确密度,即每英寸的像素点privatefloatydpi;//垂直方向上的准确密度,即没音村的像素点@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//getPixelWindowManager();//getPixelDisplayMetrics();//getPixelDisplayMetricsII();System.out.println(宽:+screenWidth+,高:+screenHeight);System.out.println(密度density:+density+,densityDpi:+densityDpi);System.out.println(精确密度xdpi:+xdpi+,ydpi:+ydpi);}privatevoidgetPixelWindowManager(){screenWidth=getWindowManager().getDefaultDisplay().getWidth();screenHeight=getWindowManager().getDefaultDisplay().getHeight();}privatevoidgetPixelDisplayMetrics(){DisplayMetricsdm=newDisplayMetrics();dm=getResources().getDisplayMetrics();screenWidth=dm.widthPixels;screenHeight=dm.heightPixels;density=dm.density;densityDpi=dm.densityDpi;xdpi=dm.xdpi;ydpi=dm.ydpi;}privatevoidgetPixelDisplayMetricsII(){DisplayMetricsdm=newDisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);screenWidth=dm.widthPixels;screenHeight=dm.heightPixels;density=dm.density;densityDpi=dm.densityDpi;xdpi=dm.xdpi;ydpi=dm.ydpi;}}执行getPixelWindowManager()方法结果:02-2216:19:38.925:I/System.out(29606):宽:1280,高:75202-2216:19:38.925:I/System.out(29606):密度density:0.0,densityDpi:002-2216:19:38.925:I/System.out(29606):精确密度xdpi:0.0,ydpi:0.0执行getPixelDisplayMetrics()方法结果:02-2216:20:40.225:I/System.out(29763):宽:1280,高:75202-2216:20:40.225:I/System.out(29763):密度density:1.0,densityDpi:16002-2216:20:40.225:I/System.out(29763):精确密度xdpi:149.82489,ydpi:150.51852执行getPixelDisplayMetricsII()方法结果:02-2216:21:11.230:I/System.out(29911):宽:1280,高:75202-2216:21:11.230:I/System.out(29911):密度density:1.0,densityDpi:16002-2216:21:11.230:I/System.out(29911):精确密度xdpi:149.82489,ydpi:150.518522.真实密度(像素计算)和归一化密度(物理长度计算)px与dp换算公式:px=dip*density/160;计算像素点使用的是归一化密度,计算实际尺寸使用的是精确的物理密度;真实密度:每英寸含有的像素点数,拿我使用的三星GT-N8000为例,水平方向上的真实密度为每英寸149.82像素,垂直方向上的真实密度为每英寸150.51像素;--运算不按照该方式:按照该密度计算1280dp对应的是1280*149.82/160=1198.4个像素;举例:给一个Textview控件设置1280dp的宽度,然后可以看到该组件横向沾满宽度,按照实际运算该1280dp对应的是1198个像素,是无法占满整个屏幕的;XML布局文件:效果图:归一化密度:在Android中从DisplayMetrics中获取的density和densityDpi就是归一化密度;--固定值:归一化的密度是有固定值的,这个固定值是120dpi(ldpi),160dpi(mdpi),240dpi(ldpi),320dpi(xldpi),480dpi(xxldpi)Android中计算像素使用的密度是这五个值之一;--实际尺寸不准确:如果想要在屏幕上划出1英寸的直线,使用归一化密度计算这个值是错误的;下面计算三星GT-N8000中水平方向上100dip所占有的像素个数和实际长度:--计算像素个数:计算像素个数需要使用归一化密度,该设备的归一化密度为160dpi,因此根据px=dip*densityDpi/160,进行计算,px=100*160/160,对应的像素个数为100px;--计算实际尺寸:按照英寸计算,先计算出像素个数,然后根据像素个数和精确物理密度计算实际尺寸,上面计算出了像素个数为100px,水平方向上每英寸149.82489个像素,100px/149.82489px/inch*1inch=0.6674inch,因此100dpi对应的实际尺寸为0.6674英寸;.3.Android中资源适配(1)图片资源适配图片资源失真问题:图片资源的大小是按照像素计算的,在密度不同的时候显示大小也不相同,因此会根据密度的不同制作不同像素的图片,以避免失真;--低密度手机显示:如果在低密度的手机上,分辨率低,图片占用像素个数不变,图片会显得很大;--高密度手机显示:如果在高密度的手机上,分辨率高,图片占用像素个数不变,图片会显得很小;根据密度选择资源:根据屏幕密度选择