Android Q完全禁止NavigationBar滑出来

背景

最近项目集成了三方锁屏应用,系统针对这个应用也需要做相应的特殊处理,比如禁用NavigationBar全部功能

google提供了隐藏NavigationBar的API,但这个API只能在隐藏并不能完全禁止NavigationBar,如果自己从底部还是可以将NavigationBar滑出来的

 View decorView = getWindow().getDecorView();
 int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN;
 decorView.setSystemUiVisibility(uiOptions);

修改方法

所以我们需要从framework层完全禁止SystemUI将NavigationBar滑出来
/frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java

mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler,
                new SystemGesturesPointerEventListener.Callbacks() {
                    @Override
                    public void onSwipeFromTop() {
                        if (mStatusBar != null) {
                           requestTransientBars(mStatusBar);
                        }
                    }
                    @Override
                    public void onSwipeFromBottom() {
                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
                            requestTransientBars(mNavigationBar);
                        }
                    }
                    @Override
                    public void onSwipeFromRight() {
                        final Region excludedRegion;
                        synchronized (mLock) {
                            excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
                        }
                        final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
                                || mNavigationBarPosition == NAV_BAR_RIGHT;
                        if (mNavigationBar != null && sideAllowed
                                && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
                            requestTransientBars(mNavigationBar);
                        }
                    }
                    @Override
                    public void onSwipeFromLeft() {
                        final Region excludedRegion;
                        synchronized (mLock) {
                            excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
                        }
                        final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
                                || mNavigationBarPosition == NAV_BAR_LEFT;
                        if (mNavigationBar != null && sideAllowed
                                && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
                            requestTransientBars(mNavigationBar);
                        }
                    }
                    @Override
                    public void onFling(int duration) {
                        if (mService.mPowerManagerInternal != null) {
                            mService.mPowerManagerInternal.powerHint(
                                    PowerHint.INTERACTION, duration);
                        }
                    }

                    @Override
                    public void onDebug() {
                        // no-op
                    }

                    private WindowOrientationListener getOrientationListener() {
                        final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
                        return rotation != null ? rotation.getOrientationListener() : null;
                    }

                    @Override
                    public void onDown() {
                        final WindowOrientationListener listener = getOrientationListener();
                        if (listener != null) {
                            listener.onTouchStart();
                        }
                    }

                    @Override
                    public void onUpOrCancel() {
                        final WindowOrientationListener listener = getOrientationListener();
                        if (listener != null) {
                            listener.onTouchEnd();
                        }
                    }

                    @Override
                    public void onMouseHoverAtTop() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
                        mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
                    }

                    @Override
                    public void onMouseHoverAtBottom() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
                        mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
                    }

                    @Override
                    public void onMouseLeaveFromEdge() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                    }
                    /* add by cheng.luo for MMITest on 2019-07-15 - BEGIN */
                    private boolean isGestureIsolated() {
                        WindowState win = mFocusedWindow != null
                                ? mFocusedWindow : mTopFullscreenOpaqueWindowState;
                        return isMMITestTop(win);
                        /* add by cheng.luo for MMITest on 2019-07-15 - BEGIN */
                    }
                });

这是关于手势操作的一些回调比如onSwipeFromTop,onSwipeFromBottom,onSwipeFromLeft,onSwipeFromRight等等,分别对于从上往下滑,从下往上滑,从左往右滑,从右往左滑等,核心都是调用requestTransientBars

requestTransientBars

此方法最终会到SystemUI去控制StatusBar和NavigationBar的动作

private void requestTransientBars(WindowState swipeTarget) {
        synchronized (mLock) {
            if (!mService.mPolicy.isUserSetupComplete()) {
                // Swipe-up for navigation bar is disabled during setup
                return;
            }
            //检查是否满足滑动StatusBar的条件
            boolean sb = mStatusBarController.checkShowTransientBarLw();
            //检查是否满足滑动NavigationBar的条件
            boolean nb = mNavigationBarController.checkShowTransientBarLw()
                    && !isNavBarEmpty(mLastSystemUiFlags);
            if (sb || nb) {
                // Don't show status bar when swiping on already visible navigation bar
                if (!nb && swipeTarget == mNavigationBar) {
                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
                    return;
                }
                if (sb) mStatusBarController.showTransient();
                if (nb) mNavigationBarController.showTransient();
                if (!SystemProperties.getBoolean("ro.vendor.tct.mmitest", false)){
                    mImmersiveModeConfirmation.confirmCurrentPrompt();
                }
                updateSystemUiVisibilityLw();
            }
        }
    }

所以我们想完全禁用NavigationBar或者StatusBar就可以在上面回调中做相应判断,此方法中能够获取当前窗口的windowState,有了windowState就能够做足够判断了,比如我的需求是在三方锁屏的界面用户不可以通过底部上滑出Navigation,我就在onSwipeFromBottom里面判断当前窗口为三方锁屏则直接return

发布了28 篇原创文章 · 获赞 40 · 访问量 4807

猜你喜欢

转载自blog.csdn.net/qq_34211365/article/details/103731219