android 屏幕分辨率与密度,dip与px的区别(整合自网络资源)
获得屏幕的高度和宽度:
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,是因为他去掉了状态栏的高度,
从网上找过不少资料,发现获取屏幕尺寸并不是很复杂的编程操作,下面的代码即可获取屏幕的尺寸。
在一个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 plain copy print ?- //获取屏幕密度(方法1)
- intscreenWidth=getWindowManager().getDefaultDisplay().getWidth();//屏幕宽(像素,如:480px)
- intscreenHeight=getWindowManager().getDefaultDisplay().getHeight();//屏幕高(像素,如:800p)
- Log.e(TAG+"getDefaultDisplay","screenWidth="+screenWidth+";screenHeight="+screenHeight);
- //获取屏幕密度(方法2)
- DisplayMetricsdm=newDisplayMetrics();
- dm=getResources().getDisplayMetrics();
- floatdensity=dm.density;//屏幕密度(像素比例:0.75/1.0/1.5/2.0)
- intdensityDPI=dm.densityDpi;//屏幕密度(每寸像素:120/160/240/320)
- floatxdpi=dm.xdpi;
- floatydpi=dm.ydpi;
- Log.e(TAG+"DisplayMetrics","xdpi="+xdpi+";ydpi="+ydpi);
- Log.e(TAG+"DisplayMetrics","density="+density+";densityDPI="+densityDPI);
- screenWidth=dm.widthPixels;//屏幕宽(像素,如:480px)
- screenHeight=dm.heightPixels;//屏幕高(像素,如:800px)
- Log.e(TAG+"DisplayMetrics(111)","screenWidth="+screenWidth+";screenHeight="+screenHeight);
- //获取屏幕密度(方法3)
- dm=newDisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(dm);
- density=dm.density;//屏幕密度(像素比例:0.75/1.0/1.5/2.0)
- densityDPI=dm.densityDpi;//屏幕密度(每寸像素:120/160/240/320)
- xdpi=dm.xdpi;
- ydpi=dm.ydpi;
- Log.e(TAG+"DisplayMetrics","xdpi="+xdpi+";ydpi="+ydpi);
- Log.e(TAG+"DisplayMetrics","density="+density+";densityDPI="+densityDPI);
- intscreenWidthDip=dm.widthPixels;//屏幕宽(dip,如:320dip)
- intscreenHeightDip=dm.heightPixels;//屏幕宽(dip,如:533dip)
- Log.e(TAG+"DisplayMetrics(222)","screenWidthDip="+screenWidthDip+";screenHeightDip="+screenHeightDip);
- screenWidth=(int)(dm.widthPixels*density+0.5f);//屏幕宽(px,如:480px)
- screenHeight=(int)(dm.heightPixels*density+0.5f);//屏幕高(px,如:800px)
- Log.e(TAG+"DisplayMetrics(222)","screenWidth="+screenWidth+";screenHeight="+screenHeight);
结果如下:
[java] view plain copy print ?
- E/==MyScreenActivity===================================getDefaultDisplay(8509):screenWidth=320;screenHeight=533
- E/==MyScreenActivity===================================DisplayMetrics(8509):xdpi=156.3077;ydpi=157.51938
- E/==MyScreenActivity===================================DisplayMetrics(8509):density=1.0;densityDPI=160
- E/==MyScreenActivity===================================DisplayMetrics(111)(8509):screenWidth=320;screenHeight=533
- E/==MyScreenActivity===================================DisplayMetrics(8509):xdpi=234.46153;ydpi=236.27907
- E/==MyScreenActivity===================================DisplayMetrics(8509):density=1.5;densityDPI=240
- E/==MyScreenActivity===================================DisplayMetrics(222)(8509):screenWidthDip=320;screenHeightDip=533
- 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 推荐使用这个,不依赖像素。
- importandroid.content.Context;
- importandroid.util.DisplayMetrics;
- /**
- *计算公式pixels=dips*(density/160)
- *
- *@version1.0.12010-12-11
- *
- *@author
- */
- publicclassDensityUtil{
- privatestaticfinalStringTAG=DensityUtil.class.getSimpleName();
- //当前屏幕的densityDpi
- privatestaticfloatdmDensityDpi=0.0f;
- privatestaticDisplayMetricsdm;
- privatestaticfloatscale=0.0f;
- /**
- *
- *根据构造函数获得当前手机的屏幕系数
- *
- **/
- publicDensityUtil(Contextcontext){
- //获取当前屏幕
- dm=newDisplayMetrics();
- dm=context.getApplicationContext().getResources().getDisplayMetrics();
- //设置DensityDpi
- setDmDensityDpi(dm.densityDpi);
- //密度因子
- scale=getDmDensityDpi()/160;
- Logger.i(TAG,toString());
- }
- /**
- *当前屏幕的density因子
- *
- *@paramDmDensity
- *@retrunDmDensityGetter
- **/
- publicstaticfloatgetDmDensityDpi(){
- returndmDensityDpi;
- }
- /**
- *当前屏幕的density因子
- *
- *@paramDmDensity
- *@retrunDmDensitySetter
- **/
- publicstaticvoidsetDmDensityDpi(floatdmDensityDpi){
- DensityUtil.dmDensityDpi=dmDensityDpi;
- }
- /**
- *密度转换像素
- **/
- publicstaticintdip2px(floatdipValue){
- return(int)(dipValue*scale+0.5f);
- }
- /**
- *像素转换密度
- **/
- publicintpx2dip(floatpxValue){
- return(int)(pxValue/scale+0.5f);
- }
- @Override
- publicStringtoString(){
- return"dmDensityDpi:"+dmDensityDpi;
- }
- }
在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
状态栏和标题栏高个38px或者25dip
横屏是屏幕宽度800px 或者800dip,工作区域高度442px或者480dip
竖屏时屏幕宽度480px或者480dip,工作区域高度762px或者775dip
更多相关文章
- android手势 事件
- android View绘制流程
- Android(安卓)自动解锁 KeyguardManager(键盘管理器)
- android 强制横屏的方法
- Android(安卓)屏幕常亮
- 设置屏幕默认横屏
- android中View坐标学习
- Android(安卓)8.0 悬浮窗变动与用法
- Android(安卓)开发中,px、dip、density 间的关系,用于多分辨率适配