Android 解决界面底部弹出dialog被虚拟按键遮挡一部分的问题

本文介绍在Android中实现Activity及Dialog全屏显示的方法,并提供了自动隐藏虚拟按键的解决方案。

原文链接: http://blog.csdn.net/shengyakun1/article/details/54174893

 

(吐槽一下原文排版好难看. 所以我自己调整了下~)

 

Android 部分机型没有物理按键,只有虚拟按键,Activity全屏方法如下:

1、在这句

 

setContentView(R.layout.activity_main);

 

之前添加

 

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

 

2、当用户划出虚拟按键后,自动再隐藏方法如下:

 

getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
    @Override
    public void onSystemUiVisibilityChange(int visibility) {
        int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                //布局位于状态栏下方
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
                //全屏
                View.SYSTEM_UI_FLAG_FULLSCREEN |
                //隐藏导航栏
                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        if (Build.VERSION.SDK_INT >= 19) {
            uiOptions |= 0x00001000;
        } else {
            uiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
        }
        getWindow().getDecorView().setSystemUiVisibility(uiOptions);
    }
});

 

3、dialog 隐藏方法

 

 

mDialog.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
mDialog.getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
    @Override
    public void onSystemUiVisibilityChange(int visibility) {
        int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                //布局位于状态栏下方
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
                //全屏
                View.SYSTEM_UI_FLAG_FULLSCREEN |
                //隐藏导航栏
                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        if (Build.VERSION.SDK_INT >= 19) {
            uiOptions |= 0x00001000;
        } else {
            uiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
        }
        mDialog.getWindow().getDecorView().setSystemUiVisibility(uiOptions);
    }
});

 

要在mDialog.show();之前。

 

 

我用上面的方法解决了这一问题.有个地方注意下:

3、dialog 隐藏方法   里原作者使用的全屏设置,效果是弹出dialog时原来的页面会变为全屏,我不需要该功能,所以把

 

View.SYSTEM_UI_FLAG_FULLSCREEN |

这一句给去了就可以了.

 

记录下这个问题.
 

<think>我们正在讨论的是Android窗口系统中的DisplayArea,特别是容纳非Activity窗口(系统窗口)的DisplayArea在手机上的具体表现形式。用户特别询问了这种DisplayArea是否表现为分屏形式,还是其他形式。 根据引用[1]和[2]的内容,我们知道: - 非App窗口(系统窗口)如状态栏、导航栏、壁纸窗口等,它们被组织在特定的DisplayArea中。 - 这些DisplayArea是按层级(z-order)组织的,而不是按屏幕空间划分(如分屏)。 具体回答如下: 1. **非Activity窗口的DisplayArea不是分屏形式**:分屏通常是指将屏幕分成多个区域,每个区域显示不同的应用(Activity)。而容纳非Activity窗口(系统窗口)的DisplayArea是用于管理窗口的层级(z轴顺序),而不是屏幕的空间划分(x/y轴)。因此,它不会表现为分屏。 2. **具体表现形式**: - **层级叠加**:这些DisplayArea中的窗口(如状态栏、导航栏)会覆盖在应用窗口之上或之下,形成层次结构。例如,状态栏位于屏幕顶部,始终显示在最上层;导航栏位于屏幕底部,也显示在上层;而壁纸窗口则显示在最底层。 - **独立于应用窗口**:这些系统窗口不会与应用窗口共享同一块屏幕区域(除了覆盖关系),它们有自己固定的位置和大小(如状态栏在顶部,导航栏在底部),并且不会将屏幕分割成多个可交互的区域(像分屏那样)。 3. **层级结构示例**(参考引用[1]): - 最高层:StatusBar(状态栏)、NavigationBar(导航栏)等,它们位于`DisplayArea.Tokens`中,类型为`TYPE_STATUS_BAR`和`TYPE_NAVIGATION_BAR`。 - 中间层:应用窗口(Activity、Dialog等)位于`ApplicationArea`。 - 最底层:壁纸窗口(Wallpaper)位于`WallpaperWindowToken`。 4. **视觉表现**: - 当用户使用手机时,状态栏始终显示在屏幕最顶部,覆盖在应用内容之上。 - 导航栏(虚拟按键或手势条)始终显示在屏幕底部,也覆盖在应用内容之上。 - 输入法窗口(键盘)弹出时,会出现在屏幕底部,覆盖在应用窗口之上,但位于导航栏之下(如果导航栏存在的话)。 - 壁纸则显示在所有窗口的最底层,被应用窗口覆盖。 5. **与分屏的区别**: - 分屏(Multi-Window)是将屏幕分割成多个部分,每个部分运行不同的Activity,属于应用窗口之间的空间划分。 - 而系统窗口的DisplayArea是全局的,它们独立于应用窗口,并且总是以覆盖的形式出现在屏幕上。 因此,容纳非Activity窗口的DisplayArea在手机上的具体表现是**层级叠加的覆盖窗口**,而不是分屏形式。 --- ### 相关问题 1. 系统窗口的DisplayArea层级顺序是如何确定的? 2. 在折叠屏设备上,系统窗口的DisplayArea管理有何不同? 3. 如何通过代码创建一个属于特定DisplayArea的系统窗口? 4. 窗口管理器(WindowManager)如何确保系统窗口始终位于正确的层级? [^1]: 窗口按层级划分为App之上、App和App之下的窗口,分别由不同的容器管理。 [^2]: 非App窗口是系统为了特定目的而使用的特殊类型窗口。</think>在Android系统中,容纳非Activity窗口(系统窗口)的`DisplayArea`**不是分屏形式**,而是通过**层级叠加(Z轴顺序)** 实现窗口管理。具体表现形式如下: ### 一、核心表现形式:层级叠加而非分屏 1. **非空间分割** `DisplayArea`不分割屏幕物理区域(如分屏将屏幕切分为多块),而是按**Z轴层级**组织窗口: - 状态栏、导航栏等系统窗口位于独立`DisplayArea`(如`StatusBarArea`) - 这些窗口**始终覆盖在应用窗口之上**,形成视觉叠加效果 - 示例:全屏游戏时,状态栏仍悬浮在游戏画面顶部[^1][^2] 2. **分层容器结构** 系统通过`DisplayArea.Tokens`容器管理非Activity窗口: ```java // 层级结构伪代码 DisplayContent (屏幕根容器) ├── StatusBarArea (状态栏区域, DisplayArea.Tokens) ├── NavigationBarArea (导航栏区域, DisplayArea.Tokens) ├── IMEArea (输入法区域) └── ApplicationArea (应用窗口区域) ``` - 每个`DisplayArea.Tokens`容纳同类型窗口(如所有状态栏窗口) - 窗口按预设Z-order排序,系统窗口层级 > 应用窗口层级[^1] ### 二、具体视觉表现 | 场景 | 表现形式 | 示例 | |------|----------|------| | **正常使用** | 系统窗口悬浮在应用上方 | 状态栏覆盖在微信界面顶部 | | **全屏应用** | 系统窗口自动隐藏/半透明 | 游戏时导航栏缩为细线 | | **输入法弹出** | 动态调整层级边界 | 键盘覆盖输入框但不遮挡状态栏 | | **多任务** | 独立于分屏机制 | 分屏时两个Activity共享同一屏幕区域,状态栏仍全局置顶 | ### 三、与分屏的本质区别 | 特性 | 非Activity窗口的DisplayArea | 分屏(多窗口) | |------|----------------------------|--------------| | **管理目标** | 系统窗口(z-order) | 应用窗口(空间分割) | | **层级关系** | 固定覆盖关系 | 同级并列关系 | | **容器类型** | DisplayArea.Tokens | TaskDisplayArea | | **修改方式** | 系统预设不可调整 | 用户手动拖拽调整 | ### 四、技术原理 通过`WindowManager.LayoutParams.type`定义窗口层级: ```java // 状态栏窗口类型 (高于应用层级) params.type = LayoutParams.TYPE_STATUS_BAR; // 输入法窗口类型 (介于应用和系统栏之间) params.type = LayoutParams.TYPE_INPUT_METHOD; ``` 系统根据type值将窗口分配到对应`DisplayArea`,最终由SurfaceFlinger按Z-order合成渲染[^1][^2]。 > ⚠️ 关键结论:非Activity窗口的`DisplayArea`表现为**全局悬浮覆盖层**,而非屏幕空间分割。其核心是通过Z轴层级管理确保系统窗口始终可见。 --- ### 相关问题 1. 如何通过代码验证某个窗口所属的DisplayArea类型? 2. 在折叠屏设备中,状态栏的DisplayArea会如何适应屏幕形态变化? 3. DisplayArea.Tokens与TaskDisplayArea在窗口管理中有何协作机制? 4. 系统窗口的Z-order值具体如何设定?是否存在动态调整场景? [^1]: 非App窗口(系统窗口)由系统创建并管理,具有独立的层级区域。 [^2]: 窗口按层级划分为App之上、App和App之下的窗口,分别由不同的容器管理。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值