如何在Android中获取屏幕大小,包括虚拟按键?

6

对于普通使用,您可以使用DisplayMetrics类并获取“可渲染”大小,但我想弄清实际物理屏幕尺寸,其中包括虚拟按钮的高度。

在我的Galaxy Nexus上,无论我尝试什么,报告的大小都是1196x720,我可以用什么来获得物理大小,即1280x720?Nexus 7、Nexus 4和Nexus 10设备也是如此。

更新:这是我现在使用的最终代码,包括修复:

    //Activity A = this;
    DisplayMetrics displayMetrics = new DisplayMetrics();
    WindowManager wm = (WindowManager) A.getApplicationContext().getSystemService(Context.WINDOW_SERVICE); 
    Display disp = wm.getDefaultDisplay();

    int API_LEVEL =  android.os.Build.VERSION.SDK_INT;
    if (API_LEVEL >= 17)
    {
        disp.getRealMetrics(displayMetrics);
    }
    else
    {
        disp.getMetrics(displayMetrics);
    }

    int Width = displayMetrics.widthPixels;
    int Height = displayMetrics.heightPixels;

展示你正在使用的代码。 - Squonk
2个回答

6
你应该使用Display.getRealSize(Point),它是在官方文档这里中介绍的。显示区域有两种不同的描述方式。应用程序显示区域指的是可能包含应用程序窗口的显示部分,不包括系统装饰。应用程序显示区域可能比实际显示区域小,因为系统会减去需要装饰元素(如状态栏)的空间。使用以下方法查询应用程序显示区域:getSize(Point),getRectSize(Rect)和getMetrics(DisplayMetrics)。真正的显示区域指的是包含内容(包括系统装饰)的显示部分。即使如此,如果窗口管理器正在使用(adb shell am display-size)模拟较小的显示屏,则真正的显示区域可能比显示器的物理大小小。使用以下方法查询真正的显示区域:getRealSize(Point),getRealMetrics(DisplayMetrics)。

从API级别17(4.2)开始可用!这基本上意味着没有4.2更新的旧三星平板电脑,没有其他方法可以获得真实大小吗? - RelativeGames
您可以尝试使用DisplayMetrics.widthPixels/heightPixels来适配旧版本。 - a.bertucci
不行,因为我已经尝试过了。噢好吧,我主要是需要它用于Nexus设备,希望4.X能够更快地被采用。 - RelativeGames
2
是的,我明白。不幸的是,Display API (<17) 旨在仅返回“可呈现”区域大小。很遗憾这样的功能被引入得如此晚。 - a.bertucci

4
类似问题的答案似乎有解决方案可以在API小于17时获取显示器的实际大小。具体请参考https://dev59.com/hnNA5IYBdhLWcg3wUL5Y#15699681
WindowManager w = activity.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
// since SDK_INT = 1;
widthPixels = metrics.widthPixels;
heightPixels = metrics.heightPixels;
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
try {
    widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);
    heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 17)
try {
    Point realSize = new Point();
    Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
    widthPixels = realSize.x;
    heightPixels = realSize.y;
} catch (Exception ignored) {
}

稍微注意一下,如果 Display 类没有那个方法,它会抛出 java.lang.NoSuchMethodError 异常,这个异常不是 Exception 的子类(它是 Throwable 的子类),因此您无法捕获该异常并且程序会崩溃。 - RelativeGames
我刚刚验证了,在这种情况下会抛出java.lang.NoSuchMethodException(而不是NoSuchMethodError),它派生自Exception,所以代码应该没问题。 - orcy
为什么要使用invoke而不是直接使用d.getRealSize(realSize)? - Pawel Cioch
Pawel Cioch,我认为它也可以直接调用。只有在针对SDK < 17构建APK时才需要反射。 - orcy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接