一、经常使用单位及其关系html
px:像素java
inch:英寸android
pt:1/72 英寸git
dpi:一英寸长的直线上的像素点的数量,即像素密度。不一样的设备,dpi值不一样,显示效果不一样,dpi的值跟设备硬件有关。标准值是160dp。github
dp(dip):独立像素密度。即在标准屏幕下,1个像素点的长度,标准屏幕是160dpi,能够理解为1英寸长度上有160个像素。标准屏幕中1dp=1px。网络
px = dp*(dpi/160);//当dpi=160时,1px=1dpapp
分辨率:屏幕上长宽方向上像素点的数量,即一个屏幕上像素的数量。ide
例如:720*1280 = 屏幕x轴上有720个像素,屏幕y轴上有1280个像素函数
分辨率单位:dpi(点每英寸)、lpi(线每英寸)、ppi(像素每英寸)工具
屏幕的物理尺寸:屏幕对角线的长度,单位是inch
sp:专用于设定文字大小,受dpi影响和用户的字体偏好设定影响。
各单位和px的换算关系见TypedValue.applyDimension方法
public static float applyDimension(int unit, float value, DisplayMetrics metrics) { switch (unit) { case COMPLEX_UNIT_PX: return value; case COMPLEX_UNIT_DIP: return value * metrics.density; case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; }
//显示器 DisplayMetrics d = getResources().getDisplayMetrics();//能够得到scaledDensity,densityDpi,heightPixels,widthPixels等信息。 Configuration configuration = getResources().getConfiguration();//获取设备的配置信息 //configuration.screenHeightDp 当前屏幕可用空间的高度,单位是dp //configuration.screenWidthDp 当前屏幕可用空间的宽度,单位是dp //configuration.densityDpi 当前设备的dpi信息
例子:
已知设备1080*1920,使用DisplayMetrics获取的实际信息是1080*1776,y轴方向上的像素有偏差是由于软键盘,实际屏幕要小。
使用Configuration获取的设备的dpi=480dpi,根据公式px=dp*(dpi/160)。
如今px=1080,dpi=480,则dp=360.
使用configuration.screenWidthDp获得的数值为360,和上面用公式算出的一致。
可是y轴方向上用公式计算出来的应该是1776/3=592.可是用scrrenHeightDp获取的只有567。
经过源码验证上述是否成立:
applyDimension方法就是经过输入的任何值转换成px,也就是说,该方法是任何单位和px的换算关系。
COMPLEX_UNIT_DIP 就是dip单位,就是平时说的dp。和px的换算关系是
value * metrics.density;
metrics.density是密度,默认值是
SystemProperties.getInt("qemu.sf.lcd_density",SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT)) / 160
160是中密度屏幕的标准dpi
因此屏幕密度density=设备dpi/160
DENSITY_DEFAULT=160
densityDpi=SystemProperties.getInt("qemu.sf.lcd_density",SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT))/ DENSITY_DEFAULT
density= densityDpi/ DENSITY_DEFAULT
scaledDensity=density
xdpi= densityDpi
ydpi= densityDpi
可是实际上获得的xdpi!=ydpi的
xdpi:x轴屏幕每英寸的实际物理像素
二、换算方程式
px=dp*(dpi/160) px=sp* metrics.scaledDensity px=sp*(dpi/160) px=pt*xdpi*(1.0f/72) pt*(1/72)=inch px=inch*xdpi px=mm*xdpi*(1.0f*25.4f) mm*(1.0f/25.4f)=inch
易乱点:
分辨率1080*1920单位是像素,有的认为单位是dpi,可是经过源码验证,单位就是px
物理尺寸单位是inch
dpi跟设备有关系
只有在dpi=160时,1px=1dp
三、资源查找原则
app运行时,系统会根据属性选择适配的资源进行展现。若是有符合的资源则使用,反之,当符合的资源不存在时,系统会去寻找最相近的可用资源来代替。可是,查找的属性不一样,查找的顺序会有全部差别。
res文件夹下的资源文件以优先级从高到低排列,命名规则:资源名-属性1-属性2-…..
v15修饰的资源仅用于4.0及以上的设备
w640dp修饰的适配640dp宽度的设备
h720dp修饰的资源适配720dp高度的设备
屏幕密度属性ldpi、mdpi、hdpi、xhdpi、xxhdpi、nodpi、tvdpi
ldpi=120
mdpi=160
hdpi=240
xhdpi=320
xxhdpi=480
xxxhdpi=640
其中nodpi用于开发者不但愿系统对图片进行缩放的状况
tvdpi介于hdpi和mdpi之间。tvdpi通常在213左右,多用于android系统的只能电视,大部分app不多用到
对dpi属性来讲,查找的顺序为,高dpi的资源优先。例如,没能找到hdpi的图片资源,则系统的搜索顺序是
drawable-xhdpi->drawable-xxhdpi->drawable-mdip->drawable->drawable->drawable-ldpi。
这里drawable被认为比drawable-ldpi更接近hdpi。
有时候,咱们的图片资源不必定是从drawable文件夹中读取的,还有多是从sd卡上读取的,或者从网络上下载的。这个时候,咱们须要注意,默认状况下,经过BitmapFactory.decodeFile()函数生成的图片被认为是MDPI的,若是想让图片也得到与drawable文件夹类似的缩放能力,则须要经过BitmapFactory.Option.inDensity属性设置(例如若是图片是为hdpi准备的,则设置为240)。
对于screan size,查找的顺序则是小尺寸优先,大尺寸放弃。例如,在Galaxy note 2上执行apk时,若是未能找到layout-large资源,则查找顺序为:layout-normal->layout->layout-small,不会查找layout-xlarge。
四、屏幕适配方案一
步骤:
1) 假设设计图的基准是720*1280,那么在设计图中1px对于1920*1080分辨率的手机应该是1.5px
在布局文件中就能够直接使用像素标识了,其实本质上是百分比
布局文件中的使用,好比说如今作一个670*80px的按钮,在density=1的时候,1dp=1px,在density=2.0的手机,1px=2.0dp,在density=1.5的手机中1px=1.5dp
若是使用dp设置这个button的大小,以2.0为基准,设置大小335*40dp,
在density=1.5的手机上,实际占的大小是502.5*60px。若是手机的分辨率是480*800px的就会出现button显示不全的状况。
可是,使用上面指定分辨率属性资源的,根据不一样的手机分辨率应用自动寻找对应的资源文件。dimen_670_dip*dimen_80_dip在分辨率720*1280手机中是670*80px
在1080*1920分辨率的手机中是1005*120px。不须要计算就能够获得相应的尺寸。(不须要人为去计算,根据资源查找原则,系统会自动选择最适合屏幕的资源)
<Button android:layout_width="@dimen/dimen_670_dip" android:layout_height="@dimen/dimen_80_dip" android:text="登录" />
由于大小按照不一样的手机不一样的分辨率进行了适配,可是字体也要进行适配。否则大小变小了,字体没有适配就会出现过小或太大的问题。
pt和sp的换算关系还跟用户的设置有关系,因此最好的方法就是,字体大小也使用px单位的换算。
五、屏幕适配方案二-------谷歌百分比布局库
android-support-percent.jar
方案一的适配已经运用在多款互联网应用,可是方案一的适配有一个缺点,就是会增长apk的大小。
使用谷歌的百分比布局库就能够解决这个问题
百分比布局库就是讲RelativeLayout换成PercentRelativeLayout,
将FrameLayout换成PercentFrameLayout
支持宽高设置和margin设置
Eclipse中直接将jar复制进libs文件夹,并依赖库percent
F:\Android\SDK\extras\android\support\percent
sdk路径/extras/android/support/percent
AndroidStudio在build.gradle中添加compile 'com.android.support:percent:22.2.0'
使用示例
<android.support.percent.PercentRelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="0dp" android:layout_height="0dp" app:layout_heightPercent="20%" app:layout_widthPercent="30%" android:text="w:30%,h:20%" /> </android.support.percent.PercentRelativeLayout>
六、经常使用方法
/** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } /** * 根据手机的分辨率从 px(像素) 的单位 转成为 dp */ public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } public static int getScreenWidth(Activity activity){ DisplayMetrics dm = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(dm); int screenWidth = dm.widthPixels; return screenWidth; } public static int getScreenHeigth(Activity activity){ DisplayMetrics dm = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(dm); int screenHeigh = dm.heightPixels; return screenHeigh; } public static int measureHeight(View view){ int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); view.measure(w, h); int height =view.getMeasuredHeight(); return height; } public static int measureWidth(View view){ int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); view.measure(w, h); int width =view.getMeasuredWidth(); return width; }
注意:
该适配方法只适用于手机。平板不适用该方法的适配。
参考资料:
谷歌官方资料:http://developer.android.com/guide/topics/resources/providing-resources.html
Android屏幕适配工具包(像素最大值是599px,sp最大值是49sp):http://download.csdn.net/detail/zmobs/8597341
屏幕分辨率信息查询:http://screensiz.es/phone
百分比布局库使用示例:https://github.com/JulienGenoud/android-percent-support-lib-sample
Android屏幕适配工具包2(像素最大值是2000px,sp最大值是200)http://download.csdn.net/detail/qq_27570955/9653790
开源,原创,实用Android 屏幕适配方案分享:http://blog.csdn.net/i7788/article/details/44937277
Android多屏幕适配学习笔记