Android开发之透明导航栏状态栏后与软键盘产生冲突的问题解决

本文介绍了解决Android应用中透明导航栏状态栏与软键盘冲突的问题,通过监听全局布局变化,调整根布局的margin来确保输入框不会被软键盘遮挡。

在开发的时候会碰到遮掩的一个问题,将状态栏以及导航栏透明之后,在点击编辑框弹出软件盘的时候会出现软键盘将编辑框挡住了的现象,这个时候修改manifest也不起作用,这是由于透明导航栏状态栏后与软键盘产生了冲突,导致编辑框被遮挡。
解决的方法参考的是http://blog.youkuaiyun.com/silentweek/article/details/53118492,这篇文章,但是我做了一些修改,我将向上移的布局修改为根布局,就是说activity最外层布局,获取最外层布局的集中方法如下:

getParent(获取上一级View)
getRootView
getWindow().getDecorView()
findViewById(android.R.id.content)
((ViewGroup)findViewById(android.R.id.content)).getChildAt(0)

最后总结下来的代码如下:


    @Override
    protected void onCreate(Bundle savedInstanceState) {
    。。。。
            setContentView(R.layout.activity_base);
        //沉浸式通知栏使用(以下三个语句必须同时启用或同时关闭)
        //透明状态栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        //透明导航栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        //设置透明状态栏以及导航栏与软键盘弹出的冲突问题(软键盘弹出收回监听)
        getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);

。。。。

}
    private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        private View rootView = null;
        @Override
        public void onGlobalLayout() {
            if(!CheckUtils.isNotEmptyOrNull(rootView)){//检测是否为空
                rootView = findViewById(android.R.id.content);
            }
            if(CheckUtils.isNotEmptyOrNull(rootView)) {
                Rect rect = new Rect();
                getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
                int screenHeight = getScreenHeight();
                int heightDifference = screenHeight - rect.bottom;//计算软键盘占有的高度  = 屏幕高度 - 视图可见高度

                if (rootView.getLayoutParams() instanceof RelativeLayout.LayoutParams) {
                    RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) rootView.getLayoutParams();
                    layoutParams.setMargins(0, 0, 0, heightDifference);//设置rlContent的marginBottom的值为软键盘占有的高度即可
                } else if (rootView.getLayoutParams() instanceof LinearLayout.LayoutParams) {
                    LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) rootView.getLayoutParams();
                    layoutParams.setMargins(0, 0, 0, heightDifference);//设置rlContent的marginBottom的值为软键盘占有的高度即可
                }
                rootView.requestLayout();
            }
        }


        private int getScreenHeight(){
            WindowManager manager = getWindowManager();
            DisplayMetrics outMetrics = new DisplayMetrics();
            manager.getDefaultDisplay().getMetrics(outMetrics);
            int height = outMetrics.heightPixels;
            return  height;
        }
    };

最后不要忘了在界面销毁的时候移除监听:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //退出looper
        if(android.os.Build.VERSION.SDK.compareTo("18") < 0) {
            handlerThread.quit();
        }else {
            handlerThread.quitSafely();
        }
        //移除软键盘弹出收回监听(解决隐藏状态栏以及导航栏导致和软件盘冲突的解决所添加的监听)
        if(CheckUtils.isNotEmptyOrNull(onGlobalLayoutListener)){
            getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }
<think>嗯,用户想在Android 10设备上实现隐藏导航栏状态栏以及进入全屏模式。我需要先回忆一下Android的相关API和实现方式。首先,全屏模式通常可以通过设置Window的flags来实现。比如,SYSTEM_UI_FLAG_FULLSCREEN用于隐藏状态栏,SYSTEM_UI_FLAG_HIDE_NAVIGATION隐藏导航栏,还有SYSTEM_UI_FLAG_IMMERSIVE_STICKY可以让这些栏在用户滑动时暂时显示,然后自动隐藏。这些标志应该添加到View的setSystemUiVisibility方法中,不过这个方法在API 30以后被弃用了,可能需要用WindowInsetsController来代替。但用户提到的是Android 10,也就是API 29,所以还是可以用旧的方法。 然后,用户可能需要不同的实现方式,比如在Activity中设置,或者通过WindowManager添加视图。记得引用中的内容,比如引用[1]提到隐藏状态栏和操作栏进入内容导向模式,引用[2]提到创建navigationBarView并添加到windowManager中。还有引用[3]中的setFullScreenIntent方法,可能用于通知触发全屏。不过用户的问题主要是如何隐藏,所以可能需要结合这些方法。 需要分步骤说明,比如在Activity的onCreate中使用setSystemUiVisibility,或者通过主题设置。另外,全屏模式可能需要处理布局的调整,比如fitSystemWindows属性。还有沉浸式模式的不同类型,比如sticky和non-sticky的区别。用户可能还需要处理用户交互后的系统栏重新出现的情况,这时候需要添加监听器来重新隐藏。 另外,提到PIP模式的引用[4]可能和全屏相关,但用户的问题主要是隐藏导航栏状态栏,所以可能不需要深入PIP,但可以作为相关功能提一下。然后,生成相关问题的时候,需要考虑用户可能进一步想知道如何保持全屏,或者处理输入焦点变化等情况。 需要确保代码示例正确,比如使用View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION等组合,并注意这些flag在Android 10中的兼容性。同时,检查是否有其他方法,比如通过WindowManager.LayoutParams的flags,或者修改主题中的windowFullscreen属性。 可能还需要提到如何处理边缘情况,比如弹出软键盘时系统栏的显示,或者在不同生命周期中维持全屏状态。此外,引用[3]中的setFullScreenIntent可能通知相关,当通知触发时启动全屏的Activity,这也是一种实现方式,但用户的问题更偏向于当前Activity的全屏设置。 最后,总结几种方法,包括代码示例和注意事项,确保用户能够根据需求选择合适的方式,并处理常见的陷阱,比如退出全屏后的恢复,或者兼容性处理。</think>### Android 10全屏模式实现方法 #### 1. **通过系统UI标志动态控制** 在`Activity`的`onCreate`或`onResume`方法中添加以下代码,可动态隐藏状态栏导航栏: ```java View decorView = getWindow().getDecorView(); int flags = View.SYSTEM_UI_FLAG_FULLSCREEN // 隐藏状态栏 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // 隐藏导航栏 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; // 手势触发后自动隐藏 decorView.setSystemUiVisibility(flags); ``` **注意**:此方法需在每次界面恢复时重新设置(如从其他应用返回时)[^1]。 #### 2. **通过主题配置静态设置** 在`styles.xml`中定义全屏主题: ```xml <style name="FullScreenTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowFullscreen">true</item> <item name="android:windowTranslucentNavigation">true</item> </style> ``` 在`AndroidManifest.xml`中应用该主题: ```xml <activity android:name=".MainActivity" android:theme="@style/FullScreenTheme"/> ``` 此方式可避免界面恢复时的状态丢失问题[^2]。 #### 3. **通过WindowManager强制控制** 对于需要覆盖系统UI的场景(如锁屏界面): ```java WindowManager.LayoutParams params = getWindow().getAttributes(); params.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; getWindow().setAttributes(params); ``` #### 4. **处理布局适配** 在布局XML中添加以下属性避免内容被遮挡: ```xml android:fitsSystemWindows="true" ``` ### 关键问题解决方案 | 问题类型 | 解决方法 | |----------------|------------------------------------------------------------------------| | 手势冲突 | 使用`SYSTEM_UI_FLAG_LAYOUT_STABLE`保持布局稳定 | | 输入法弹出遮挡 | 添加`adjustResize`窗口软输入模式 | | 兼容性问题 | 使用`ViewCompat.setOnApplyWindowInsetsListener`处理不同API版本 | ### 注意事项 1. 避免同时使用`FLAG_FULLSCREEN`和`SYSTEM_UI_FLAG_FULLSCREEN` 2. 全屏模式下需自行处理返回按钮逻辑 3. 视频类应用建议结合`PIP`模式实现(引用[4])
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值