Android获取当前设备屏幕信息(分辨率,密度以及物理尺寸)

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

如何获取DisplayMetics对象:

DisplayMetrics display=
new DisplayMetrics();

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

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

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

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

一、分辨率

需要注意的原来经常使用的getHeight()与getWidth()已经不推荐使用了,建议使用getSize()来替代。

此方法原型如下:

[java] view
plain
copy

  1. public void getSize(Point outSize) {
  2. synchronized (this) {
  3. updateDisplayInfoLocked();
  4. mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
  5. outSize.x = mTempMetrics.widthPixels;
  6. outSize.y = mTempMetrics.heightPixels;
  7. }
  8. }

参数是一个返回参数,用以返回分辨率的Point,这个Point也比较简单,我们只需要关注x和y这两个成员就可以了。

用法如下:

[java] view
plain
copy

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

结果如下:

[plain] view
plain
copy

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

此外Display又提供了一个getRealSize方法,原型如下:

[java] view
plain
copy

  1. public void getRealSize(Point outSize) {
  2. synchronized (this) {
  3. updateDisplayInfoLocked();
  4. outSize.x = mDisplayInfo.logicalWidth;
  5. outSize.y = mDisplayInfo.logicalHeight;
  6. }
  7. }

从两个方法的实现上看是有区别的,但是在通常情况下二者的返回值相同。那么差异究竟在哪里,下面做一些实验来验证一下。

首先,我将Acitvity设置不同的theme,比如:

[html] view
plain
copy

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

结果还是相同的。

接下来将我的Activity父类变成ActionBarActivity,如下:

public class MainActivity extends ActionBarActivity

期望ActionBar会占用一些屏幕,并在程序中动态设置Listview的Item中的图片大小。在机缘巧合之下,

结果验证了在这种情况下,getSize返回的结果变了。

代码如下:

[java] view
plain
copy

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

Log如下:

[plain] view
plain
copy

  1. D/MainActivity﹕ the screen size is Point(800, 1202)
  2. 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
plain
copy

  1. DENSITY_LOW = 120
  2. DENSITY_MEDIUM = 160  //默认值
  3. DENSITY_TV = 213      //TV专用
  4. DENSITY_HIGH = 240
  5. DENSITY_XHIGH = 320
  6. DENSITY_400 = 400
  7. DENSITY_XXHIGH = 480
  8. DENSITY_XXXHIGH = 640

举例如下:

[java] view
plain
copy

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

Log如下:

[plain] view
plain
copy

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

有了这些信息,我们是不是就可以计算屏幕尺寸了呢?

首先求得对角线长,单位为像素。

然后用其除以密度(densityDpi)就得出对角线的长度了。

代码如下:

[java] view
plain
copy

  1. private void getScreenSizeOfDevice() {
  2. DisplayMetrics dm = getResources().getDisplayMetrics();
  3. int width=dm.widthPixels;
  4. int height=dm.heightPixels;
  5. double x = Math.pow(width,2);
  6. double y = Math.pow(height,2);
  7. double diagonal = Math.sqrt(x+y);
  8. int dens=dm.densityDpi;
  9. double screenInches = diagonal/(double)dens;
  10. Log.d(TAG,"The screenInches "+screenInches);
  11. }

Log如下:

[plain] view
plain
copy

  1. 01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ the screen size is Point(1600, 2438)
  2. 01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ the screen real size is Point(1600, 2560)
  3. 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
  4. 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
plain
copy

  1. 01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ the screen size is Point(1600, 2560)
  2. 01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ the screen real size is Point(1600, 2560)
  3. 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
  4. 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
plain
copy

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

屏幕X/Y轴上真正的物理PPI。

Yes!Got it!

为了保证获得正确的分辨率,我还是使用getRealSize去获得屏幕宽和高像素。所以,经过修改,代码如下:

[java] view
plain
copy

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

Log is as follows:

[plain] view
plain
copy

  1. 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
plain
copy

  1. //pixel = dip*density;
  2. private int convertDpToPixel(int dp) {
  3. DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
  4. return (int)(dp*displayMetrics.density);
  5. }
  6. private int convertPixelToDp(int pixel) {
  7. DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
  8. return (int)(pixel/displayMetrics.density);
  9. }

参考:

http://stackoverflow.com/questions/19155559/how-to-get-android-device-screen-size

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 12:23:02

Android获取当前设备屏幕信息(分辨率,密度以及物理尺寸)的相关文章

Android获取cpu和内存信息、网址的代码

android获取手机cpu并判断是单核还是多核 /** * Gets the number of cores available in this device, across all processors. * Requires: Ability to peruse the filesystem at "/sys/devices/system/cpu" * @return The number of cores, or 1 if failed to get result */ pri

Android 获取手机设备等的信息

获取手机设备型号等信息: 如图华为P6手机获取是手机设备信息值: 代码如下: tvStr = (TextView) findViewById(R.id.tv_titlebar); String phoneInfo = "Product: " + android.os.Build.PRODUCT + "\n"; phoneInfo += "CPU_ABI: " + android.os.Build.CPU_ABI + "\n";

android 获取手机设备品牌

在有些数据要获取手机设备是什么品牌,特别做一些适配的时候,好了就讲下怎样或者手机是什么品牌: String brand =android.os.Build.BRAND; 就这么简单!

[Swift4.2互动教程]七、常见概念-(13)使用UIScreen查询设备屏幕信息

本文将为你演示,如何获得设备的屏幕信息,了解设备的屏幕尺寸等信息,才能做出适配性更好的应用程序. 首先导入需要使用到的界面工具框架 import UIKit 然后通过UIScreen类,就可以获得设备的屏幕信息.这里获得设备的屏幕尺寸,点击显示结果图标,查看获得的结果 UIScreen.main.availableModes.description 从结果列表中可以看出,屏幕的宽度为2048像素,高度为1536像素.再次点击结果图标,关闭结果列表. [<UIScreenMode: ox60000

android获取apk安装包信息

public class TestActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.main);  String archiveFilePath="sdcard/jb51.net.apk";//安装包路径  PackageManager p

android -------- 获取手机设备信息

最近在开发中,需要用到一些系统信息,总结了一下 /** * Created by zhangqie on 2019/2/26 * Describe: 系统工具类 */ public class EquipmentUtil { /** * 获取当前手机系统语言. * * @return 返回当前系统语言.例如:当前设置的是“中文-中国”,则返回“zh-CN” */ public static String getSystemLanguage() { return Locale.getDefault

Android获取Build和内存,分辨率等信息

package com.zms.getdeviceinfo; import android.app.ActivityManager; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.support.v7.app.ActionBarActivity; import

[android] 获取系统的联系人信息

内容提供是实质上是个接口,后门,他给别人提供数据,系统联系人是个比较复杂的内容通过者. 找到/data/data/com.android.providers.contacts/contacts2.db 这个目录下还有个文件contacts2.db.-journal,这个文件和数据库的事务相关 联系人应用数据库的主要结构 raw_contacts 联系人表 contact_id 联系人id data数据表  raw_contact_id联系人id,mimetype_id数据类id,data1数据

Android获取各种设备的状态

WIFI 获取WIFI状态 WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); if(wifiManager != null){ int wifiState = wifiManager.getWifiState(); } 附:Wifi状态有以下几种:(括号内为所对应的的int值) 1. wifiManager.WIFI_STATE_DISABLED (1) 2. wifiMa