Android获取应用窗口尺寸:适配分屏、弹窗视图等场景
全场景应用窗口净尺寸计算(Java实现)
要搞定普通全屏、分屏、三星弹窗这些场景下的窗口净尺寸(不含状态栏、导航栏),核心是抓准系统UI的占用区域,同时适配不同Android版本的API,下面是具体实现:
1. 优先用API 30+的WindowInsets(适配绝大多数新设备)
从Android 11开始,官方的WindowInsets API能直接拿到系统UI的Insets,而且自动适配各种多窗口模式,不用额外处理:
// 在Activity中实现 View rootView = getWindow().getDecorView().getRootView(); rootView.setOnApplyWindowInsetsListener((view, windowInsets) -> { // 获取状态栏、导航栏的Insets Insets insets = windowInsets.getInsets(WindowInsets.Type.systemBars()); // 计算净尺寸:根视图宽高减去系统UI的左右、上下占用 int usableWidth = view.getWidth() - insets.left - insets.right; int usableHeight = view.getHeight() - insets.top - insets.bottom; // 此处可使用计算出的净尺寸进行业务逻辑处理 Log.d("WindowSize", "净宽度: " + usableWidth + ", 净高度: " + usableHeight); // 必须返回处理后的Insets,否则系统会反复调用该监听 return windowInsets.consumeSystemWindowInsets(); });
2. 兼容Android 5到Android 10(API 21-29)
老设备可以通过ViewTreeObserver监听布局完成,再结合getWindowVisibleDisplayFrame获取可见区域:
View rootView = getWindow().getDecorView().getRootView(); rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // 移除监听避免重复触发 rootView.getViewTreeObserver().removeOnGlobalLayoutListener(this); // 获取屏幕整体尺寸 DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); // 获取窗口实际可见区域(自动排除状态栏、导航栏,多窗口时也会排除外部区域) Rect visibleFrame = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame); // 净尺寸即为可见区域的宽高 int usableWidth = visibleFrame.width(); int usableHeight = visibleFrame.height(); Log.d("WindowSize", "净宽度: " + usableWidth + ", 净高度: " + usableHeight); } });
3. 三星弹窗模式适配说明
三星的弹窗模式属于Android多窗口的细分场景,上面两种方案都能自动适配——不管是WindowInsets还是getWindowVisibleDisplayFrame,都会识别弹窗的实际边界,返回对应的可用区域,无需额外编写适配代码。
注意事项
- 不要在
onCreate中直接获取尺寸!此时View还未完成布局,会得到0值,必须等View布局完成后通过监听获取 - 如果是全屏隐藏状态栏/导航栏的场景,Insets会返回0,此时净尺寸就是根视图的实际宽高
- 折叠屏设备同样适用这套逻辑,系统会自动处理折叠状态下的可用区域
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

