通过查找发现,在Android
4.0(Api14)就提供了getRealSize()这个方法,只不过是系统隐藏了,我们不能直接去调用。那么能不能通过反射的方式来使用呢?
publicstaticintgetScreenHeight5(Activity activity) {
Point realSize = newPoint();
Display display = activity.getWindowManager().getDefaultDisplay();
try{
Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
} catch(Exception e) {
e.printStackTrace();
}
returnrealSize.y;
}
和我们预期的一样在Android
4.0也获取到了数据。
其实系统在Android
3.2(Api13)开始加入了如下方法,只不过一直是隐藏的API:
publicintgetRawHeight() {
inth = getRawHeightNative();
if(DEBUG_DISPLAY_SIZE) Slog.v(
TAG, "Returning raw display height: "+ h);
returnh;
}
privatenativeintgetRawWidthNative();
当然我们可以通过反射的方式来调用它:
publicstaticintgetScreenHeight6(Activity activity) {
intheightPixels =0;
Display display = activity.getWindowManager().getDefaultDisplay();
try{
heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
} catch(Exception e) {
e.printStackTrace();
}
returnheightPixels;
}
Android 版本
版本号
getRawHeight()
getRealSize(Point p)
Android
3.2
13
包含(隐藏)
Android
4.0,4.0.1,4.0.2
14
包含(隐藏)
包含(隐藏)
Android
4.0.3,4.0.4
15
包含(隐藏)
包含(隐藏)
Android
4.1,4.1.1
16
包含(隐藏)
包含(隐藏)
Android
4.2,4.2.2
17
包含(隐藏)
包含
...
...
...
...
...
...
...
...
综上,我们可以得到一个比较完整的获取系统屏幕高度的方法:
publicintgetRealHeight(Activity activity) {
intheightPixels =0;
Display display = activity.getWindowManager().getDefaultDisplay();
finalintVERSION = Build.VERSION.SDK_INT;
if(VERSION <13) {
display.getHeight();
}elseif(VERSION ==13) {
try{
heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
} catch(Exception e) {
}
} elseif(VERSION >=14&& VERSION <17) {
Point realSize = newPoint();
try{
Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
heightPixels = realSize.y;
} catch(Exception e) {
}
} else{
Point realSize = newPoint();
display.getRealSize(realSize);
heightPixels = realSize.y;
}
returnheightPixels;
}
简化一下就是:
publicintgetRealHeight(Activity activity) {
intheightPixels =0;
Display display = activity.getWindowManager().getDefaultDisplay();
finalintVERSION = Build.VERSION.SDK_INT;
if(VERSION <13) {
display.getHeight();
}elseif(VERSION ==13) {
try{
heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
} catch(Exception e) {
}
} else{
Point realSize = newPoint();
try{
Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
heightPixels = realSize.y;
} catch(Exception e) {
}
}
returnheightPixels;
}
四、获取屏幕尺寸
以上我们为什么费了那么大劲非要搞到屏幕的真实高度呢?我们又没有办法控制下方的导航栏,得到真实高度也没什么卵用,其实我们获取真实的屏幕高度是为了计算屏幕的高度。那么屏幕的物理尺寸怎么去计算呢?
1.
屏幕物理尺寸是屏幕对角线的长度,单位英寸;
2.
屏幕的像素点密度(ppi) ≠ dp;
3.
屏幕物理宽度 = width / xppi;
4.
屏幕物理高度 = height / yppi;
我们发现 DisplayMetrics 中有如下两个变量:
publicfloatxdpi;
publicfloatydpi;
没错,这就是我们要找的在宽度和高度上的ppi(每英寸内的像素点数目)。
publicstaticfloatgetWidthPpi(Activity activity) {
DisplayMetrics displayMetrics = newDisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
returndisplayMetrics.xdpi;
}
publicstaticfloatgetHeightPpi(Activity activity) {
DisplayMetrics displayMetrics = newDisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
returndisplayMetrics.ydpi;
}
那么获取宽高的物理尺寸也就简单了:
publicstaticfloatgetWidthInch(Activity activity) {
intrealWidth = getRealWidth(activity);
return(float)realWidth / getWidthPpi(activity);
}
publicstaticfloatgetHeightInch(Activity activity) {
intrealHeight = getRealHeight(activity);
return(float)realHeight / getHeightPpi(activity);
}
根据勾股定理,宽度和高度的尺寸都知道了,对角线的长度就是长度平方加上高度平方再开平方:
publicstaticfloatgetScreenInch(Activity activity) {
return(float)Math.sqrt(Math.pow(getWidthInch(activity),2) + Math.pow(getHeightInch(activity),2));
}
五、获取长宽DP
知道DP和PPI的关系,以及屏幕的长宽值之后想要获取屏幕长度和宽度上的总dp就比较简单了。首先通过代码得到dp和ppi(dpi)的对应关系:
publicstaticfloatgetScreenDensity(Activity activity) {
DisplayMetrics displayMetrics = newDisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
returndisplayMetrics.density;
}
然后用屏幕宽高除以
屏幕密度就是宽高上的dp数目:
publicstaticfloatgetScreenWidthDp(Activity activity) {
returngetScreenWidth(activity) / getScreenDensity(activity);
}
publicstaticfloatgetScreenHeightDp(Activity activity) {
returngetScreenHeight(activity) / getScreenDensity(activity);
}
publicstaticfloatgetRealWidthDp(Activity activity) {
returngetRealWidth(activity) / getScreenDensity(activity);
}
publicstaticfloatgetRealHeightDp(Activity activity) {
returngetRealHeight(activity) / getScreenDensity(activity);
}
六、判断是手机还是平板
有时候在一套代码跑在手机和平板上,所以就要根据是平板还是pad来设置不同的布局。当然手机和平板公用一套代码显然不是一个好的方案,也确实能减小项目的开发维护成本。
以下为几种方案:
1.
判断设备是否具备通话功能
2.
判断设备是否大于6英寸
3.
判断设备是否为大尺寸
第一种方案不太有效,因为现在好多平板也是可以打电话的。判断设备是否大于6英寸是一个常用的做法:
publicstaticbooleanisMoreThan6Inch(Activity activity) {
returngetScreenInch(activity) >=6.0;
}
第三种判断是否为大尺寸设备:
publicstaticbooleanisScreenSizeLarge(Context context) {
return(context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
我们开看下SCREENLAYOUT_SIZE_LARGE
是怎么定义的:
publicstaticfinalintSCREENLAYOUT_SIZE_LARGE =0x03;
可以看到是判断的屏幕高度和宽度的dp数目,他要求最小为