systemui中动态禁用虚拟导航栏(二)

上一篇介绍了屏幕手势滑动流程,下面介绍下setSystemUiVisibility()流程,代码依然是基于Android11介绍,网上有关这部分的介绍大部分的view处理逻辑还是在PhonewindowManager类中,Android11已经分离这部分,可参考下本篇。

上一篇连接:systemui中动态禁用虚拟导航栏(一)

当我们想要在activity层级隐藏显示导航栏或状态栏时,会通过类似下面设置不同flag方式实现功能

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);

代码流程:

view->setSystemUiVisibility;

ViewRootImpl->recomputeViewAttributes->scheduleTraversals->doTraversal->performTraversals->relayoutWindow->mWindowSession.relayout;

WindowSession->WindowManagerGlobal.getWindowSession()->WindowManagerService

@UnsupportedAppUsage
    public static IWindowManager getWindowManagerService() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowManagerService == null) {
                sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
                try {
                    if (sWindowManagerService != null) {
                        ValueAnimator.setDurationScale(
                                sWindowManagerService.getCurrentAnimatorScale());
                        sUseBLASTAdapter = sWindowManagerService.useBLAST();
                    }
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowManagerService;
        }
    }

    @UnsupportedAppUsage
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    // Emulate the legacy behavior.  The global instance of InputMethodManager
                    // was instantiated here.
                    // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }

WindowManagerGlobal类中推断session来自WindowManagerService的openSession()方法,Session是IWindowSession.Stub的实现。

Session->relayout(ViewRootImpl中的relayout()方法)->mService.relayoutWindow回到WindowManagerService类中;

WindowManagerService->relayoutWindow()->updateFocusedWindowLocked()->mRoot.updateFocusedWindowLocked();

RootWindowContainer->dc.updateFocusedWindowLocked();

DisplayContent->updateFocusedWindowLocked()->performLayout()->performLayoutNoTrace()->mDisplayPolicy.beginLayoutLw()

DisplayPolicy->layoutNavigationBar()-mNavigationBarController.setBarShowingLw();

BarController->updateStateLw()->statusbar.setWindowState(mDisplayId, mStatusBarManagerId, state);

又回到上篇的逻辑

 private boolean updateStateLw(@StatusBarManager.WindowVisibleState final int state) {
        if (mWin != null && state != mState) {
            mState = state;
            if (DEBUG) Slog.d(mTag, "mState: " + StatusBarManager.windowStateToString(state));
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    StatusBarManagerInternal statusbar = getStatusBarInternal();
                    if (statusbar != null) {
                        statusbar.setWindowState(mDisplayId, mStatusBarManagerId, state);
                    }
                }
            });
            return true;
        }
        return false;
    }

CommandQueue是接口StatusBarManagerInternal的实现操作类,可以看上篇了解

最终会调用NavigationBarFragment类中setWindowState()方法。

至于想要如何动态监听禁用导航栏,可以按照上篇的方法,也可以在本章中某个流程禁用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值