大家帮忙喽!

博主参加2014博客之星活动,大家帮忙投票啦!猛击这里!

通过程序去了解硬件情况是一件十分有意思的事情。很早我就研究在WM6.5上获得屏幕物理尺寸,但一直没有成功。后来又想要在Android上有所突破,不过在今天之前得到的尺寸都不准确。虽然很多人认为没必要这么较真,因为貌似很多情况下用不到。不过我就当这是一件很有挑战性的事,一定要做到。对,就是这么任性。

源码中android.view包下的Display类提供了很多方法供程序员获得显示相关的信息,通过此类让我们开启了解设备屏幕之旅吧。

一、分辨率

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

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

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

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

结果如下:

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

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

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

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

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返回的结果变了。
代码如下:

    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如下:

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这个成员,它有如下几个常用值:

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

举例如下:

    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如下:

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)就得出对角线的长度了。
代码如下:

    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如下:

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再算一遍。

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,对其描述是:

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

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

    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:

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。
实例代码如下:

    //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);} 

参考:

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

Android实战技巧之十:获得屏幕物理尺寸、密度及分辨率相关推荐

  1. android 速度传感器,Android实战技巧之四十二:加速度传感器

    传感器字面上的意思就是传递感觉的仪器,哪些感觉呢? 视觉.听觉.味觉.触觉.嗅觉等等. 所以有人说,传感器的存在和发展,让物体有了触觉.味觉和嗅觉等感官,让物体慢慢变得活了起来. 当前Android设 ...

  2. Android实战技巧之十六:getprop与dumpsys命令

    Android设备连接PC后,我们可以通过adb命令完成绝大多数工作.下面借助getprop.dumpsys来了解一些系统相关信息. 一.getprop 此命令的原理很简单,就是从系统的各种配置文件中 ...

  3. Android实战技巧之十六 getprop与dumpsys命令

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Andr ...

  4. Android实战技巧之十二:Android Studio导入第三方类库、jar包和so库

    第三方类库源码 将一网友的XMPP代码从ADT转到AS时,发现其使用了第三方类库,源码放在了lib下,直接在AS中Import project,第三方类库并没有自动导入进来,看来需要自己动手了. 项目 ...

  5. android studio导入jar包和so库,Android实战技巧之十二:Android Studio导入第三方类库、jar包和so库(示例代码)...

    第三方类库源码 将一网友的XMPP代码从ADT转到AS时,发现其使用了第三方类库,源码放在了lib下,直接在AS中Import project,第三方类库并没有自动导入进来,看来需要自己动手了. 项目 ...

  6. Android实战技巧之三十九:短信收发

    7月4日从广州出差回来就定下写作计划,但迟迟没有动笔.耽搁的原因还是老样子,工作上又有新任务,全部精力都投入过去了,每天精疲力竭的回来也打不起精神做其他事了.这就是精力管理不当所致,就像我把很多要做的 ...

  7. Android实战技巧之四十:Android5.1.1源代码编译与烧写

    购买Nexus手机的朋友大多是为了自己修改系统玩,再加上其较高的性价比,在开发者中还是广受欢迎的.我的5太子被我升级到了6.0预览版,玩的正嗨,舍不得换回到5.1时代了.不过鉴于距6.0源码发布还有段 ...

  8. Android实战技巧之四十 Android5 1 1源代码编译与烧写

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 购买Ne ...

  9. Android实战技巧之十八:adb取出安装在手机中的apk

    场景: 朋友看见你Android手机中的游戏或应用很好玩,也想装一个此程序,但限于网络条件不能从网上下载.那么最简单的办法就是直接从你手机中将此apk扣出来给他安装上. pm命令 第一步,找到程序的包 ...

最新文章

  1. CXF 调用 .net webservice
  2. 腾讯技术直播间 | 轻量产品思维!手把手教你搭建在线甲醛监测系统
  3. 观察者模式在SAP UI5主题更改功能中的应用
  4. 数据库怎么看是什么编码_离婚了怎么发朋友圈?看你喜欢什么类型
  5. 搭扶梯靠右站,真的对吗?
  6. linux目录结构来源6,Linux入门基础 #6 Linux系统目录架构
  7. 前端名称命名--英文字母
  8. Steinberg Cubase Elements 11 for Mac(音频处理软件)
  9. JRuby--Java和Ruby的强强联合 Centos7.X
  10. paip.C#.net 悬浮窗口的建立总结
  11. 用友业务单据生成凭证如何修改凭证金额
  12. [落选]狗熊会人才计划第6期选拔作业
  13. 【源码+图片素材+详细教程】Java游戏开发_Java开发经典游戏飞翔的小鸟_飞扬的小鸟_Java游戏项目Flappy Bird像素鸟游戏_Java课程设计项目
  14. vim报错E45: ‘readonly‘ option is set (add ! to override)
  15. 计算机图形学 学习笔记(一):概述,直线扫描转换算法:DDA,中点画线算法,Bresenham算法
  16. 浏览器沙盒--它是什么,我们为什么需要它?
  17. 基于BPM的低代码平台如何选型
  18. 面向对象C#初级入门精讲(1)C#开发入门-徐照兴-专题视频课程
  19. GLES2.0中文API-glTexParameter
  20. 学了python可以做什么兼职,学python真的能做兼职吗?

热门文章

  1. 图像、图形、图片文件格式
  2. Python|每日一练|素数对|优化算法|素数|素数对:找出素数对
  3. 《周志明的软件架构课》学习笔记 Day13
  4. python实现酷狗音乐下载,以及利用tk界面可视化
  5. C# 程序创建word文件与表格
  6. word_state
  7. adhoc网络的定义和应用
  8. 北京大学肖臻老师《区块链技术与应用》公开课笔记:以太坊原理(一):以太坊概述、账户、状态树、交易树和收据树
  9. 软件实习-学生管理系统
  10. 贾其萃 : 笃行实践 筑梦扬帆 | 提升之路系列(二)