Android获取当前装置屏幕信息

Android获取当前装置屏幕信息(分辨率,密度以及物理尺寸)
www.MyException.Cn 网友分享于:2015-08-29 浏览:0次
Android获取当前设备屏幕信息(分辨率,密度以及物理尺寸)

要想知道屏幕的基本信息,就要先获取一个基本的类(DisplayMetics),这个对象存放着当前的窗口的一些通用信息,如显示大小,分辨率和字体等等。

如何获取DisplayMetics对象:

DisplayMetrics display=
new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(display);//将当前窗口的一些信息放在DisplayMetrics类中,

然后就可以通过dispalyMetrics类来获取当前窗口的一些信息

注:构造函数DisplayMetrics 不需要传递任何参数;getDefaultDisplay() 方法将取得的宽高维度存放于DisplayMetrics 对象中,而取得的宽高维度是以像素为单位(Pixel) ,“像素”所指的是“绝对像素”而非“相对像素”。

下面就是获取具体信息的方法:

一、分辨率
需要注意的原来经常使用的getHeight()与getWidth()已经不推荐使用了,建议使用getSize()来替代。
此方法原型如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

public void getSize(Point outSize) {  
    synchronized (this) {  
        updateDisplayInfoLocked();  
        mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);  
        outSize.x = mTempMetrics.widthPixels;  
        outSize.y = mTempMetrics.heightPixels;  
    }  
}  

参数是一个返回参数,用以返回分辨率的Point,这个Point也比较简单,我们只需要关注x和y这两个成员就可以了。
用法如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

private void getDisplayInfomation() {  
    Point point = new Point();  
    getWindowManager().getDefaultDisplay().getSize(point);  
    Log.d(TAG,"the screen size is "+point.toString());  
}  

结果如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片

D/MainActivity﹕ the screen size is Point(800, 1280)  

此外Display又提供了一个getRealSize方法,原型如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

public void getRealSize(Point outSize) {  
    synchronized (this) {  
        updateDisplayInfoLocked();  
        outSize.x = mDisplayInfo.logicalWidth;  
        outSize.y = mDisplayInfo.logicalHeight;  
    }  
}  

从两个方法的实现上看是有区别的,但是在通常情况下二者的返回值相同。那么差异究竟在哪里,下面做一些实验来验证一下。
首先,我将Acitvity设置不同的theme,比如:
[html] view plaincopy在CODE上查看代码片派生到我的代码片

android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"  
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"  

结果还是相同的。

接下来将我的Activity父类变成ActionBarActivity,如下:
public class MainActivity extends ActionBarActivity
期望ActionBar会占用一些屏幕,并在程序中动态设置Listview的Item中的图片大小。在机缘巧合之下,
结果验证了在这种情况下,getSize返回的结果变了。
代码如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

private void getDisplayInfomation() {  
    Point point = new Point();  
    getWindowManager().getDefaultDisplay().getSize(point);  
    Log.d(TAG,"the screen size is "+point.toString());  
    getWindowManager().getDefaultDisplay().getRealSize(point);  
    Log.d(TAG,"the screen real size is "+point.toString());  
}  

Log如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片

D/MainActivity﹕ the screen size is Point(800, 1202)  
D/MainActivity﹕ the screen real size is Point(800, 1280)  

如果你不能够轻易复现也不用急,保险起见,为了得到相对正确的信息还是使用getRealSize()吧。
二、屏幕尺寸
设备的物理屏幕尺寸。与几年前不同,目前的手机屏幕已经大到一只手握不下了。标配早已经到了5寸屏时代。
所谓屏幕尺寸指的是屏幕对角线的长度,单位是英寸。
然而不同的屏幕尺寸是可以采用相同的分辨率的,而它们之间的区别在与密度(density)不同。
下面先介绍一下密度的概念,DPI、PPI,最后讲解一下如何根据获得的Display信息去求出屏幕尺寸。
三、屏幕密度
屏幕密度与DPI这个概念紧密相连,DPI全拼是dots-per-inch,即每英寸的点数。也就是说,密度越大,每英寸内容纳的点数就越多。
android.util包下有个DisplayMetrics类可以获得密度相关的信息。
最重要的是densityDpi这个成员,它有如下几个常用值:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

DENSITY_LOW = 120  
DENSITY_MEDIUM = 160  //默认值  
DENSITY_TV = 213      //TV专用  
DENSITY_HIGH = 240  
DENSITY_XHIGH = 320  
DENSITY_400 = 400  
DENSITY_XXHIGH = 480  
DENSITY_XXXHIGH = 640  

举例如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

private void getDensity() {  
    DisplayMetrics displayMetrics = getResources().getDisplayMetrics();  
    Log.d(TAG,"Density is "+displayMetrics.density+" densityDpi is "+displayMetrics.densityDpi+" height: "+displayMetrics.heightPixels+  
        " width: "+displayMetrics.widthPixels);  
}  

Log如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片

the screen size is Point(1600, 2438)  
the screen real size is Point(1600, 2560)  
Density is 2.0 densityDpi is 320 height: 2438 width: 1600  

有了这些信息,我们是不是就可以计算屏幕尺寸了呢?
首先求得对角线长,单位为像素。
然后用其除以密度(densityDpi)就得出对角线的长度了。
代码如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

private void getScreenSizeOfDevice() {  
    DisplayMetrics dm = getResources().getDisplayMetrics();  
    int width=dm.widthPixels;  
    int height=dm.heightPixels;  
    double x = Math.pow(width,2);  
    double y = Math.pow(height,2);  
    double diagonal = Math.sqrt(x+y);  

    int dens=dm.densityDpi;  
    double screenInches = diagonal/(double)dens;  
    Log.d(TAG,"The screenInches "+screenInches);  
}  

Log如下:

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ the screen size is Point(1600, 2438)  
01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ the screen real size is Point(1600, 2560)  
01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ Density is 2.0 densityDpi is 320 height: 2438 width: 1600 xdpi 338.666 ydpi 338.666  
01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ The screenInches 9.112922229586951  

如Log所见,使用heightPixels得出的值是2483而不是正确的2560.从而使结果9.11反倒跟真实屏幕尺寸很接近。下面用正确的height再算一遍。
[plain] view plaincopy在CODE上查看代码片派生到我的代码片

01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ the screen size is Point(1600, 2560)  
01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ the screen real size is Point(1600, 2560)  
01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ Density is 2.0 densityDpi is 320 height: 2560 width: 1600 xdpi 338.666 ydpi 338.666  
01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ The screenInches 9.433981132056605  

结果是9.43英寸,而真实值是8.91.如果再换一个设备,那么值差的更多。说明上面的计算是错误的。
那么错在哪里呢?densityDpi是每英寸的点数(dots-per-inch)是打印机常用单位(因而也被称为打印分辨率),而不是每英寸的像素数。下面引出PPI这个概念。
四、PPI
Pixels per inch,这才是我要的每英寸的像素数(也被称为图像的采样率)。有了这个值,那么根据上面的公式就可以求导出屏幕的物理尺寸了。
还好DisplayMetrics有两个成员是xdpi和ydpi,对其描述是:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

//The exact physical pixels per inch of the screen in the X/Y dimension.  

屏幕X/Y轴上真正的物理PPI。
Yes!Got it!
为了保证获得正确的分辨率,我还是使用getRealSize去获得屏幕宽和高像素。所以,经过修改,代码如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

private void getScreenSizeOfDevice2() {  
    Point point = new Point();  
    getWindowManager().getDefaultDisplay().getRealSize(point);  
    DisplayMetrics dm = getResources().getDisplayMetrics();  
    double x = Math.pow(point.x/ dm.xdpi, 2);  
    double y = Math.pow(point.y / dm.ydpi, 2);  
    double screenInches = Math.sqrt(x + y);  
    Log.d(TAG, "Screen inches : " + screenInches);  
}  

Log is as follows:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片

01-13 16:58:50.142  17249-17249/com.linc.listviewanimation D/MainActivity﹕ Screen inches : 8.914015757534717  

五、DIP
注意不要与上面的DPI混淆,这个DIP是Density Independent Pixel,直译为密度无关的像素。
我们在布局文件中使用的dp/dip就是它。官方推荐使用dp是因为它会根据你设备的密度算出对应的像素。
公式为:pixel = dip*density

需要注意的是,我们在Java代码中对控件设置宽高是不可以设置单位的,而其自带的单位是像素。所以如果动态修改控件大小时,
我们的任务就来了,那就是将像素转换为dp。
实例代码如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片

//pixel = dip*density;  
private int convertDpToPixel(int dp) {  
    DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();  
    return (int)(dp*displayMetrics.density);  
}  

private int convertPixelToDp(int pixel) {  
    DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();  
    return (int)(pixel/displayMetrics.density);  
}   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值