android 屏幕分辨率与密度,dip与px的区别(整合自网络资源)

来源:互联网 发布:未央歌 鹿桥 知乎 编辑:程序博客网 时间:2024/05/22 10:50

获得屏幕的高度和宽度:
        DisplayMetrics metric = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metric);
        int widthPixels = metric.widthPixels;  // 屏幕宽度(像素)
        int heightPixels = metric.heightPixels;  // 屏幕高度(像素)
        
        DisplayMetrics dm = new DisplayMetrics();  
        dm = getResources().getDisplayMetrics();         
        float xdpi = dm.xdpi;             
        float ydpi = dm.ydpi; 



        int screenWidth  = getWindowManager().getDefaultDisplay().getWidth();       
        int screenHeight = getWindowManager().getDefaultDisplay().getHeight();  
        
        Log.i("widthPixels", ""+widthPixels);
        Log.i("heightPixels", ""+heightPixels);
        Log.i("xdpi", ""+xdpi);
        Log.i("ydpi", ""+ydpi);
        Log.i("screenWidth", ""+screenWidth);
        Log.i("screenHeight", ""+screenHeight);


        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        Log.i("____________________", ""+dm.heightPixels+"++++++++++++"+dm.widthPixels);

     

这里三种方式,打印出来的信息如下:

07-19 07:12:57.328: I/widthPixels(641): 1024
07-19 07:12:57.328: I/heightPixels(641): 552
07-19 07:12:57.337: I/xdpi(641): 160.0     
07-19 07:12:57.337: I/ydpi(641): 160.0
07-19 07:12:57.337: I/screenWidth(641): 1024
07-19 07:12:57.337: I/screenHeight(641): 552

07-24 02:56:05.233: I/____________________(332): 432++++++++++++240
从他们打印的信息我们可以看出,dm.xdpi;dm.ydpi;打印的只是屏幕的密度(每一寸),其它两种方式打印出来的高度与宽度都是一样的,

注:我现在这PAD的全屏高度是600,打印出来是552,是因为他去掉了状态栏的高度,



android获取屏幕尺寸、密度
    有些时候,我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸:
    从网上找过不少资料,发现获取屏幕尺寸并不是很复杂的编程操作,下面的代码即可获取屏幕的尺寸。
    在一个Activity的onCreate方法中,写入如下代码:
        DisplayMetrics metric = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metric);
        int width = metric.widthPixels;  // 屏幕宽度(像素)
        int height = metric.heightPixels;  // 屏幕高度(像素)
        float density = metric.density;  // 屏幕密度(0.75 / 1.0 / 1.5)
        int densityDpi = metric.densityDpi;  // 屏幕密度DPI(120 / 160 / 240)
    但是,需要注意的是,在一个低密度的小屏手机上,仅靠上面的代码是不能获取正确的尺寸的。比如说,一部240x320像素的低密度手机,如果运行上述代码,获取到的屏幕尺寸是320x427。因此,研究之后发现,若没有设定多分辨率支持的话,Android系统会将240x320的低密度(120)尺寸转换为中等密度(160)对应的尺寸,这样的话就大大影响了程序的编码。所以,需要在工程的AndroidManifest.xml文件中,加入supports-screens节点,具体的内容如下:
        <supports-screens
            android:smallScreens="true"
            android:normalScreens="true"
            android:largeScreens="true"
            android:resizeable="true"
            android:anyDensity="true" />
    这样的话,当前的Android程序就支持了多种分辨率,那么就可以得到正确的物理尺寸了


android中获取屏幕的长于宽,参考了网上有很多代码,但结果与实际不符,如我的手机是i9000,屏幕大小是480*800px,得到的结果却为320*533

结果很不靠谱,于是自己写了几行代码,亲测一下

测试参数:

测试环境: i9000(三星)

物理屏幕:480*800px

density :1.5

测试代码:

[java] view plaincopyprint?
  1. // 获取屏幕密度(方法1)  
  2. int screenWidth  = getWindowManager().getDefaultDisplay().getWidth();       // 屏幕宽(像素,如:480px)  
  3. int screenHeight = getWindowManager().getDefaultDisplay().getHeight();      // 屏幕高(像素,如:800p)  
  4.   
  5. Log.e(TAG + "  getDefaultDisplay""screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);  
  6.   
  7.   
  8. // 获取屏幕密度(方法2)  
  9. DisplayMetrics dm = new DisplayMetrics();  
  10. dm = getResources().getDisplayMetrics();  
  11.   
  12. float density  = dm.density;        // 屏幕密度(像素比例:0.75/1.0/1.5/2.0)  
  13. int densityDPI = dm.densityDpi;     // 屏幕密度(每寸像素:120/160/240/320)  
  14. float xdpi = dm.xdpi;             
  15. float ydpi = dm.ydpi;  
  16.   
  17. Log.e(TAG + "  DisplayMetrics""xdpi=" + xdpi + "; ydpi=" + ydpi);  
  18. Log.e(TAG + "  DisplayMetrics""density=" + density + "; densityDPI=" + densityDPI);  
  19.   
  20. screenWidth  = dm.widthPixels;      // 屏幕宽(像素,如:480px)  
  21. screenHeight = dm.heightPixels;     // 屏幕高(像素,如:800px)  
  22.   
  23. Log.e(TAG + "  DisplayMetrics(111)""screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);  
  24.   
  25.   
  26.   
  27. // 获取屏幕密度(方法3)  
  28. dm = new DisplayMetrics();  
  29. getWindowManager().getDefaultDisplay().getMetrics(dm);  
  30.   
  31. density  = dm.density;      // 屏幕密度(像素比例:0.75/1.0/1.5/2.0)  
  32. densityDPI = dm.densityDpi;     // 屏幕密度(每寸像素:120/160/240/320)  
  33. xdpi = dm.xdpi;           
  34. ydpi = dm.ydpi;  
  35.   
  36. Log.e(TAG + "  DisplayMetrics""xdpi=" + xdpi + "; ydpi=" + ydpi);  
  37. Log.e(TAG + "  DisplayMetrics""density=" + density + "; densityDPI=" + densityDPI);  
  38.   
  39. int screenWidthDip = dm.widthPixels;        // 屏幕宽(dip,如:320dip)  
  40. int screenHeightDip = dm.heightPixels;      // 屏幕宽(dip,如:533dip)  
  41.   
  42. Log.e(TAG + "  DisplayMetrics(222)""screenWidthDip=" + screenWidthDip + "; screenHeightDip=" + screenHeightDip);  
  43.   
  44. screenWidth  = (int)(dm.widthPixels * density + 0.5f);      // 屏幕宽(px,如:480px)  
  45. screenHeight = (int)(dm.heightPixels * density + 0.5f);     // 屏幕高(px,如:800px)  
  46.   
  47. Log.e(TAG + "  DisplayMetrics(222)""screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);  

结果如下:
[java] view plaincopyprint?
  1. E/== MyScreenActivity ===================================  getDefaultDisplay( 8509): screenWidth=320; screenHeight=533  
  2. E/== MyScreenActivity ===================================  DisplayMetrics( 8509): xdpi=156.3077; ydpi=157.51938  
  3. E/== MyScreenActivity ===================================  DisplayMetrics( 8509): density=1.0; densityDPI=160  
  4. E/== MyScreenActivity ===================================  DisplayMetrics(111)( 8509): screenWidth=320; screenHeight=533  
  5. E/== MyScreenActivity ===================================  DisplayMetrics( 8509): xdpi=234.46153; ydpi=236.27907  
  6. E/== MyScreenActivity ===================================  DisplayMetrics( 8509): density=1.5; densityDPI=240  
  7. E/== MyScreenActivity ===================================  DisplayMetrics(222)( 8509): screenWidthDip=320; screenHeightDip=533  
  8. E/== MyScreenActivity ===================================  DisplayMetrics(222)( 8509): screenWidth=480; screenHeight=800  
分析结果:

在onDraw()方法中

方法1和2,得到的结果都一致,均为320*533,明显不是测试机i9000的屏幕大小

方法3,将方法1和2得到的结果,乘以density后,完美的480*800,perfect!

注: density 大于1的情况下,需要设置targetSdkVersion在4-9之间,例如
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="10" />


但是,这就说明方法3一定是通用的吗?

回答是否定的,因为我也在模拟器、HTC G14物理机,以及ViewSonic、Galaxy平板上测试过,方法3在density=1.5时,放大了实际屏幕值,例如:HTC G14

在HTC G14上,实际屏幕大小,直接通过dm.widthPixels、dm.heightPixels便得到了实际物理屏幕大小(540,960)

导致无法通过一种通用的方法获取真实物理屏幕大小的原因,可能就是因为Android系统开源,不同的手机生产厂商没有统一的制造标准,来规定手机屏幕。


仔细分析代码,发现问题出在代码:

getWindowManager().getDefaultDisplay().getMetrics(dm)

Initialize a DisplayMetrics object from this display's data.

dm = getResources().getDisplayMetrics()

Return the current display metrics that are in effect for this resource object. The returned object should be treated as read-only.

最近正在做Android的UI设计,故搜集了一些Android上进行UI设计的一些资料,现和各位分享下。

首先说说density,density值表示每英寸有多少个显示点,与分辨率是两个不同的概念。

Android主要有以下几种屏:

QVGA和WQVGA屏density=120;

HVGA屏density=160;

WVGA屏density=240;

下面以480dip*800dip的WVGA(density=240)为例,详细列出不同density下屏幕分辨率信息:

当density=120时 屏幕实际分辨率为240px*400px (两个点对应一个分辨率)
状态栏和标题栏高各19px或者25dip
横屏是屏幕宽度400px 或者800dip,工作区域高度211px或者480dip
竖屏时屏幕宽度240px或者480dip,工作区域高度381px或者775dip

density=160时 屏幕实际分辨率为320px*533px (3个点对应两个分辨率)
状态栏和标题栏高个25px或者25dip
横屏是屏幕宽度533px 或者800dip,工作区域高度295px或者480dip
竖屏时屏幕宽度320px或者480dip,工作区域高度508px或者775dip

density=240时 屏幕实际分辨率为480px*800px (一个点对于一个分辨率)
状态栏和标题栏高个38px或者25dip
横屏是屏幕宽度800px 或者800dip,工作区域高度442px或者480dip
竖屏时屏幕宽度480px或者480dip,工作区域高度762px或者775dip

apk的资源包中,当屏幕density=240时使用hdpi标签的资源
当屏幕density=160时,使用mdpi标签的资源
当屏幕density=120时,使用ldpi标签的资源。
不加任何标签的资源是各种分辨率情况下共用的。
建议:布局时尽量使用单位dip,少使用px。

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


[java] view plaincopyprint?
  1. import android.content.Context;  
  2. import android.util.DisplayMetrics;  
  3.   
  4. /** 
  5.  * 计算公式 pixels = dips * (density / 160) 
  6.  *  
  7.  * @version 1.0.1 2010-12-11 
  8.  *  
  9.  * @author 
  10.  */  
  11. public class DensityUtil {  
  12.       
  13.     private static final String TAG = DensityUtil.class.getSimpleName();  
  14.       
  15.     // 当前屏幕的densityDpi  
  16.     private static float dmDensityDpi = 0.0f;  
  17.     private static DisplayMetrics dm;  
  18.     private static float scale = 0.0f;  
  19.   
  20.     /** 
  21.      *  
  22.      * 根据构造函数获得当前手机的屏幕系数 
  23.      *  
  24.      * */  
  25.     public DensityUtil(Context context) {  
  26.         // 获取当前屏幕  
  27.         dm = new DisplayMetrics();  
  28.         dm = context.getApplicationContext().getResources().getDisplayMetrics();  
  29.         // 设置DensityDpi  
  30.         setDmDensityDpi(dm.densityDpi);  
  31.         // 密度因子  
  32.         scale = getDmDensityDpi() / 160;  
  33.         Logger.i(TAG, toString());  
  34.     }  
  35.   
  36.     /** 
  37.      * 当前屏幕的density因子 
  38.      *  
  39.      * @param DmDensity 
  40.      * @retrun DmDensity Getter 
  41.      * */  
  42.     public static float getDmDensityDpi() {  
  43.         return dmDensityDpi;  
  44.     }  
  45.   
  46.     /** 
  47.      * 当前屏幕的density因子 
  48.      *  
  49.      * @param DmDensity 
  50.      * @retrun DmDensity Setter 
  51.      * */  
  52.     public static void setDmDensityDpi(float dmDensityDpi) {  
  53.         DensityUtil.dmDensityDpi = dmDensityDpi;  
  54.     }  
  55.   
  56.     /** 
  57.      * 密度转换像素 
  58.      * */  
  59.     public static int dip2px(float dipValue) {  
  60.   
  61.         return (int) (dipValue * scale + 0.5f);  
  62.   
  63.     }  
  64.   
  65.     /** 
  66.      * 像素转换密度 
  67.      * */  
  68.     public int px2dip(float pxValue) {  
  69.         return (int) (pxValue / scale + 0.5f);  
  70.     }  
  71.   
  72.     @Override  
  73.     public String toString() {  
  74.         return " dmDensityDpi:" + dmDensityDpi;  
  75.     }  
  76. }  


在Android中支持的描述大小区域的类型有以下几种。

px(pixels)——像素:不同的设备显示效果相同。举例:画一条长度为240px的横线,在480宽的模拟器上看就是一半的屏宽,而在320宽的模拟器上看就是2/3的屏宽。

dip(device independent pixels)——设备独立像素:这个和设备硬件有关,一般哦我们为了支持WCGA、HVGA和QVGA推荐使用这个,不依赖于像素。等同于dp。就是把屏幕的高分成480分,宽分成320分。举例:做一条160dip的横线,无论在320还480的模拟器上,都是一半屏的长度。

sp(scaled pixels—best for text size)——带比例的像素。主要是用于字体显示,根据google的建议,TextView的字体大小最好用sp做单位,而且TextView默认使用sp作为字号单位。

以下三个不常用:

pt(points)——磅:1pt = 1/72英寸

in(inches)——英寸

mm(millimeters)——毫米

分辨率:整个屏是多少点,比如800x480,width及height就为屏幕分辨率(为绝对宽度与高度),它是对于软件来说的显示单位,以px为单位的点。 density(密度)值表示每英寸有多少个显示点,与分辨率是两个概念。


Android支持下列所有单位。
       px(像素):屏幕上的点。
       in(英寸):长度单位。
       mm(毫米):长度单位。
       pt(磅):1/72英寸。
       dp(与密度无关的像素):一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dp = 1px。
       dip:与dp相同,多用于android/ophone示例中。
       sp(与刻度无关的像素):与dp类似,但是可以根据用户的字体大小首选项进行缩放。

       分辨率:整个屏是多少点,比如800x480,它是对于软件来说的显示单位,以px为单位的点。 density(密度)值表示每英寸有多少个显示点,与分辨率是两个概念。

       apk的资源包中,
       当屏幕density=240时使用hdpi标签的资源 
       当屏幕density=160时使用mdpi标签的资源 
       当屏幕density=120时使用ldpi标签的资源。 
       一般android设置长度和宽度多用dip,设置字体大小多用sp. 在屏幕密度为160,1dp=1px=1dip, 1pt = 160/72 sp 1pt = 1/72 英寸.当屏幕密度为240时,1dp=1dip=1.5px.


在Android中最常用到的还是px和dip。但是这两个之间到底有什么区别呢?

在HVGA屏density=160;QVGA屏density=120;WVGA屏density=240;WQVGA屏density=120 density值表示每英寸有多少个显示点,与分辨率是两个概念。不同density下屏幕分辨率信息,以480dip*800dip的 WVGA(density=240)为例。

 

density=120时 屏幕实际分辨率为240px*400px (两个点对应一个分辨率)
状态栏和标题栏高各19px或者25dip 
横屏是屏幕宽度400px 或者800dip,工作区域高度211px或者480dip
竖屏时屏幕宽度240px或者480dip,工作区域高度381px或者775dip

 

density=160时 屏幕实际分辨率为320px*533px (3个点对应两个分辨率)
状态栏和标题栏高个25px或者25dip 
横屏是屏幕宽度533px 或者800dip,工作区域高度295px或者480dip
竖屏时屏幕宽度320px或者480dip,工作区域高度508px或者775dip

 

density=240时 屏幕实际分辨率为480px*800px (一个点对于一个分辨率)
状态栏和标题栏高个38px或者25dip 
横屏是屏幕宽度800px 或者800dip,工作区域高度442px或者480dip
竖屏时屏幕宽度480px或者480dip,工作区域高度762px或者775dip
原创粉丝点击