Android 中px, pd, sp 概念以及如何做到屏幕适配

来源:互联网 发布:淘宝运营 知乎 编辑:程序博客网 时间:2024/05/17 04:28

今天又开始我的App开发,因为之前一直做的是SDK,所以涉及到界面UI很少,刚开始做Android应用的时候,没有对dp,px,sp等概念有一个深入的了解,只知道他们之间的转化,还有写个转换工具类等。做Android已经有一年多了,现在再次开始App开发,决定没遇到一个概念,必须得弄透彻。好吧,下面进入主题吧:


首先来看一下他们的基本概念:

px   :是屏幕的像素点
dp   :一个基于density的抽象单位,如果一个160dpi的屏幕,1dp=1px
dip  :等同于dp
sp   :同dp相似,但还会根据用户的字体大小偏好来缩放(建议使用sp作为文本的单位,其它用dip)


通过上面的知识我们可以看到这里只要弄懂px和dp之间的关系就可以了。那么下面重点来看一下他们两之间的关系:

针对dip和px 的关系,做以下概述:

1). px (pixels)像素 :

一个像素通常被视为图像的最小的完整采样,这个用的比较多,特别是web开发,页面基本都是使用像素作为单位的.

2). dip或dp (device independent pixels):

设备独立像素 — 这个和设备硬件有关,一般我们为了支持手机上多种分辨率,如WVGA、HVGA

和QVGA,都会使用dip作为长度的单位

下面来看一下手机屏幕类型和密度以及分辨率的对应关系

QVGA屏density=120         QVGA(240*320)
HVGA屏density=160         HVGA(320*480)
WVGA屏density=240        WVGA(480*800)
WQVGA屏density=120      WQVGA(240*400)


注:density值表示每英寸有多少个显示点,与分辨率是两个概念。


不同density下屏幕分辨率信息是不同的,以480dip*800dip的 WVGA(density=240)为例

1、当density=120时 

转化:转化系数=120/240

屏幕实际分辨率为240px*400px (两个点对应一个分辨率)

状态栏和标题栏高各19px或者25dip

横屏是屏幕宽度400px 或者800dip,工作区域高度211px或者480dip

竖屏时屏幕宽度240px或者480dip,工作区域高度381px或者775dip

2、当density=160时 

转化:转化系数=160/240

屏幕实际分辨率为320px*533px (3个点对应两个分辨率)

状态栏和标题栏高个25px或者25dip

横屏是屏幕宽度533px 或者800dip,工作区域高度295px或者480dip

竖屏时屏幕宽度320px或者480dip,工作区域高度508px或者775dip

3、当density=240时 

转化:转化系数=240/240

屏幕实际分辨率为480px*800px (一个点对于一个分辨率)

状态栏和标题栏高个38px或者25dip

横屏是屏幕宽度800px 或者800dip,工作区域高度442px或者480dip

竖屏时屏幕宽度480px或者480dip,工作区域高度762px或者775dip

我们一般在项目中会定义多个适配资源文件夹(values-XXX,drawable-XXX等)

drawable-ldpi:     屏幕密度为120的手机设备

drawable-mdpi:   屏幕密度为160的手机设备(此为baseline,其他均以此为基准,在此设备上,1dp = 1px)

drawable-hdpi:    屏幕密度为240的手机设备

drawable-xhdpi:  屏幕密度为320的手机设备

drawable-xxhdpi:屏幕密度为480的手机设备

(values也是一样,当然还有一点要注意:values和values-hdpi效果是一样的,drawable和drawable-hdpi效果也是一样的,所以一般我们都会在这两个文件夹中存放的值是一样的,如果两个都有的话,适配更好)


apk的资源包中

当屏幕density=240时,使用hdpi 标签的资源

当屏幕density=160时,使用mdpi标签的资源

当屏幕density=120时,使用ldpi标签的资源

当屏幕density=320时,使用xhdpi标签的资源

当屏幕density=480时,使用xxhdpi标签的资源

不加任何标签的资源是各种分辨率情况下共用的

所以布局时尽量使用单位dip,少使用px

dp与px换算公式:
pixs =dips * (densityDpi/160). 
dips=(pixs*160)/densityDpi

但是我们在代码里面进行转化的时候还需要有一个偏移值:0.5f

[java] view plain copy
  1. private static final float scale = mContext.getResources().getDisplayMetrics().density;  
  2.   
  3. private static final float scaledDensity = mContext.mContext.getResources().getDisplayMetrics().scaledDensity;  
  4.   
  5. /** 
  6.  * dp转成px 
  7.  * @param dipValue 
  8.  * @return 
  9.  */  
  10. public static int dip2px(float dipValue) {  
  11.     return (int) (dipValue * scale + 0.5f);  
  12. }  
  13.   
  14. /** 
  15.  * px转成dp 
  16.  * @param pxValue 
  17.  * @return 
  18.  */  
  19. public static int px2dip(float pxValue) {  
  20.     return (int) (pxValue / scale + 0.5f);  
  21. }  
  22.   
  23. /** 
  24.  * sp转成px 
  25.  * @param spValue 
  26.  * @param type 
  27.  * @return 
  28.  */  
  29. public static float sp2px(float spValue, int type) {  
  30.     switch (type) {  
  31.     case CHINESE:  
  32.         return spValue * scaledDensity;  
  33.     case NUMBER_OR_CHARACTER:  
  34.         return spValue * scaledDensity * 10.0f / 18.0f;  
  35.     default:  
  36.         return spValue * scaledDensity;  
  37.     }  
  38. }  

我们看到,这里的scale是在这个类DisplayMetrics中定义的全局变量,其实这个值就是当前手机的density/160,scaleDensity是用来px和sp之间的转化和scale差不多。还有一点就是这里转化都会有一个偏移值处理

dp这个单位可能对web开发的人比较陌生,因为一般都是使用px(像素)
但是,现在在开始android应用和游戏后,基本上都转换成用dp作用为单位了,因为可以支持多种分辨率的手机.


上面看到了px和dp之间的关系以及转化,下面在来看一下使用场景吧,就是为什么我们会使用到他们之间的转化,我们在xml中一般定义大小都是使用dp为单位的,但是有时候我们需要在代码里面设置一些间距和位置:

下面的代码

[java] view plain copy
  1. android.view.ViewGroup.LayoutParams.height  
  2. android.view.ViewGroup.LayoutParams.width  

上面这两个属性的单位为像素,但是为了兼容多种分辨率的手机,我们需要最好使用dip,时候我们可以调用以下的代码进行转换.
[java] view plain copy
  1. int heightPx= DisplayUtil.dip2px(this33);  
  2. mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = heightPx;  


当然我们有时候也会在代码中获取values文件夹中的demen.xml文件中的值,代码如下:

[java] view plain copy
  1. float height = this.getResources().getDimension(R.dimen.height);  
  2. txt.height = px2dip((int)height);//将height转化成px  

不知道他获取的就是dimens.xml文件中定义的dp值,所以这里还手动的进行了转化操作,但是发现显示的效果和我们预期不一样,然后就把值打印了一下看,尽然是两倍,就是通过getDimension方法获取到的值是dimen.xml文件中定义的值的两倍,这不科学呀,然后就search一下了,发现有三个类似的方法,

getDimension

getDimensionPixelOffset

getDimensionPixelSize

他们的功能都是不一样的:

通过一个例子来看看他们的区别:

dimen.xml:

[html] view plain copy
  1. <dimen name="activity_vertical_margin1">16dp</dimen>    
  2. <dimen name="activity_vertical_margin2">16px</dimen>    
  3. <dimen name="activity_vertical_margin3">16sp</dimen>   

代码:

[java] view plain copy
  1. float a1=getResources().getDimension(R.dimen.activity_vertical_margin1);    
  2. int a2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin1);    
  3. int a3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin1);    
  4.   
  5. float b1=getResources().getDimension(R.dimen.activity_vertical_margin2);    
  6. int b2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin2);    
  7. int b3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin3);    
  8.   
  9. float c1=getResources().getDimension(R.dimen.activity_vertical_margin3);    
  10. int c2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin3);    
  11. int c3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin3);    
  12.   
  13. Log.i("test""getDimension= "+a1+", getDimensionPixelOffset="+a2+",getDimensionPixelSize="+a3);    
  14. Log.i("test""getDimension= "+b1+", getDimensionPixelOffset="+b2+",getDimensionPixelSize="+b3);    
  15. Log.i("test""getDimension= "+c1+", getDimensionPixelOffset="+c2+",getDimensionPixelSize="+c3);      


对于设备1(1280*720,160dpi,density=1.0):

打印结果:


对于设备2(480*800,240dpi,density=1.5):

打印结果:


可见getDimension和getDimensionPixelOffset的功能差不多,都是获取某个dimen的值,如果是dp或sp的单位,将其乘以density,如果是px,则不乘;两个函数的区别是一个返回float,一个返回int.
getDimensionPixelSize则不管写的是dp还是sp还是px,都会乘以denstiy.

所以我们在使用getDimension方法获取到的值的时候就不需要进行转化了~~


下面是我在工作中进行屏幕适配的小工具:http://download.csdn.net/detail/jiangwei0910410003/8144585

是一个小Demo,运行之后,就可以得到这个设备获取资源的文件夹了,然后我们就可以在指定的文件夹中定义它的尺寸即可。


总结:dp和px的相关知识就介绍到这里了,这个只是很容易混淆的,而且在面试和笔试的时候都会遇到,所以这些概念还是弄清楚比较好啦~~

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 甘美 甘美会 昆明甘美医院 天晴甘美注射剂说明书 甘美医院试管婴儿 甘美国际医院 甘美医院电话 异甘草酸镁注射液 异甘草酸镁说明书 甘肃 甘肃组工网 甘肃省 甘肃组工 甘肃省会 甘肃教育院 甘肃省考 甘肃门户网 甘肃车牌 甘肃气温 今日甘肃 甘肃美食 甘肃气候 每日甘肃网 甘肃省委 甘肃吧 中国甘肃网 每日甘肃 甘肃网 中国甘肃 甘肃大学 甘肃在哪里 甘肃在哪 甘肃日报 甘肃教育 甘肃穷吗 甘肃沙漠 甘肃政法 甘肃海拔 甘肃风景 甘肃 旅游 甘肃景区