http://blog.csdn.net/jiangwei0910410003/article/details/40509571

今天又开始我的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

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

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

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

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

下面的代码

  1. android.view.ViewGroup.LayoutParams.height
  2. android.view.ViewGroup.LayoutParams.width

上面这两个属性的单位为像素,但是为了兼容多种分辨率的手机,我们需要最好使用dip,时候我们可以调用以下的代码进行转换.

  1. int heightPx= DisplayUtil.dip2px(this, 33);
  2. mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = heightPx;

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

  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:

  1. <dimen name="activity_vertical_margin1">16dp</dimen>
  2. <dimen name="activity_vertical_margin2">16px</dimen>
  3. <dimen name="activity_vertical_margin3">16sp</dimen>

代码:

  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. float b1=getResources().getDimension(R.dimen.activity_vertical_margin2);
  5. int b2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin2);
  6. int b3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin3);
  7. float c1=getResources().getDimension(R.dimen.activity_vertical_margin3);
  8. int c2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin3);
  9. int c3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin3);
  10. Log.i("test", "getDimension= "+a1+", getDimensionPixelOffset="+a2+",getDimensionPixelSize="+a3);
  11. Log.i("test", "getDimension= "+b1+", getDimensionPixelOffset="+b2+",getDimensionPixelSize="+b3);
  12. 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的相关知识就介绍到这里了,这个只是很容易混淆的,而且在面试和笔试的时候都会遇到,所以这些概念还是弄清楚比较好啦~~

(PS:其实写完了,我还是不太记得住~~)

[转]Android中dp,px,sp概念梳理以及如何做到屏幕适配的更多相关文章

  1. Android中dp,px,sp概念梳理以及如何做到屏幕适配

    http://blog.csdn.net/jiangwei0910410003/article/details/40509571

  2. Android中常用单位dp,px,sp之间的相互转换

    MainActivity如下: package cc.testunitswitch; import android.os.Bundle; import android.util.DisplayMetr ...

  3. Android中px, ppi, dpi, dp, dip, sp概念解析

    Android中px, ppi, dpi, dp, dip, sp概念解析

  4. Android中Cursor类的概念和用法[转]

    首页 > 程序开发 > 移动开发 > Android > 正文   Android中Cursor类的概念和用法 2011-09-07      0个评论       收藏    ...

  5. 在Android中,px,dp,dip,sp的不同之处

           最近在学习Android开发,一直没有弄清楚px,dp,dip,sp的区别.今天正好有时间,就花时间研究了一下.     众所周知,Android厂商非常多,各种尺寸的Android手机 ...

  6. Android度量单位说明(DIP,DP,PX,SP) (转帖)

    (一)概念 dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和QVGA 推荐使用这个,不 ...

  7. Android度量单位说明(DIP,DP,PX,SP)

    本文转载于:http://blog.sina.com.cn/s/blog_6b26569e0100xw6d.html (一)概念 dip: device independent pixels(设备独立 ...

  8. Android开发之dip, dp, px, sp区别

    显示单位px和dip以及sp的区别 dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和Q ...

  9. Android中的pix,sp,dp相关概念

    px( pixel) 像素,可以简单的理解为一个点或方块,用以颜色的显示(单位),一般指印刷品或屏幕设置设备的颜色显示定义. dip(device independent pixels)设备独立像素. ...

随机推荐

  1. PreResultListener使用

    PreResultListener是一个监听器接口,可以在Action处理完之后,系统转入实际视图前被回调. Struts2应用可以给Action.拦截器添加PreResultListener监听器, ...

  2. JavaScript学习总结【8】、面向对象编程

    1.什么是面向对象编程 要理解面向对象,得先搞清楚什么是对象,首先需要明确一点这里所说的对象,不是生活中的搞男女朋友对象,面向对象就是面向着对象,换在代码中,就是一段代码相中了另一段代码,自此夜以继日 ...

  3. [CSS]cursor鼠标样式

     用css控制鼠标样式的语法如下: <span style="cursor:*">文本或其它页面元素</span>  把 * 换成如下15个效果的一种:   ...

  4. new作为修饰符

    new 修饰符与 new 操作符是两个概念 new 修饰符用于声明类或类的成员,表示隐藏了基类中同名的成员.而new 操作符用于实例化一个类型 new 修饰符只能用于继承类,一般用于弥补基类设计的不足 ...

  5. make xxx Is a directory. Stop.

    转自:make xxx Is a directory. Stop. 的原因 make xxx Is a directory. Stop. 的原因 编译内核时候的一个错误提示 make: ***    ...

  6. CodeChef CBAL

    题面: https://www.codechef.com/problems/CBAL 题解: 可以发现,我们关心的仅仅是每个字符出现次数的奇偶性,而且字符集大小仅有 26, 所以我们状态压缩,记 a[ ...

  7. hg vs git :这个世界除了svn还有别的

    最近想用版本控制软件来保存汉化文件,但又觉得SVN太麻烦,于是想到了最近较为流行的分布式版本控制工具.而Git和Mercurial(意思为水银的,于是经常缩写为Hg)自然是其中最为流行的工具.大名鼎鼎 ...

  8. 十六进制字符串转化为byte数组

    工作上有这样的需求之前找了好多都不行,好不容易有个可以的赶紧留下来. 原址:http://blog.163.com/roadwalker@126/blog/static/113561841201013 ...

  9. 【HDU1538】A Puzzle for Pirates(经典的海盗问题)

    [题目] Description A bunch of pirates have gotten their hands on a hoard of gold pieces and wish to di ...

  10. 查看linux内存、cpu

    1.查看cpu数 多核cpu,包括物理多核和逻辑多核,一台机器可能有多个cpu,每个cpu可能有多核的,多个可能包括物理多核和逻辑多核. /proc/cpuinfo 文件里记录了这些信息,以下是一个核 ...