平台

Android 7.1 + RK3288

概述

从Android 4.4开始支持沉浸式全屏体验,在沉浸式全屏模式下,状态栏、 虚拟按键动态隐藏,应用可以使用完整的屏幕空间,按照 Google 的说法,给用户一种 “身临其境” 的体验。
增加了 IMMERSIVE 和 IMMERSIVE_STICKY 标记,可以用这两个标记与 SYSTEM_UI_FLAG_HIDE_NAVIGATION 和 SYSTEM_UI_FLAG_FULLSCREEN 一起使用, 来实现沉 浸模式。

全屏的是通过隐藏状态栏和导航栏实现, 服务之间的交互如下:

#mermaid-svg-7yKLVL1n6jjHbCmt .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .label text{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .node rect,#mermaid-svg-7yKLVL1n6jjHbCmt .node circle,#mermaid-svg-7yKLVL1n6jjHbCmt .node ellipse,#mermaid-svg-7yKLVL1n6jjHbCmt .node polygon,#mermaid-svg-7yKLVL1n6jjHbCmt .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-7yKLVL1n6jjHbCmt .node .label{text-align:center;fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .node.clickable{cursor:pointer}#mermaid-svg-7yKLVL1n6jjHbCmt .arrowheadPath{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-7yKLVL1n6jjHbCmt .flowchart-link{stroke:#333;fill:none}#mermaid-svg-7yKLVL1n6jjHbCmt .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-7yKLVL1n6jjHbCmt .edgeLabel rect{opacity:0.9}#mermaid-svg-7yKLVL1n6jjHbCmt .edgeLabel span{color:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-7yKLVL1n6jjHbCmt .cluster text{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-7yKLVL1n6jjHbCmt .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-7yKLVL1n6jjHbCmt text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-7yKLVL1n6jjHbCmt .actor-line{stroke:grey}#mermaid-svg-7yKLVL1n6jjHbCmt .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-7yKLVL1n6jjHbCmt #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .sequenceNumber{fill:#fff}#mermaid-svg-7yKLVL1n6jjHbCmt #sequencenumber{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt #crosshead path{fill:#333;stroke:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .messageText{fill:#333;stroke:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-7yKLVL1n6jjHbCmt .labelText,#mermaid-svg-7yKLVL1n6jjHbCmt .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-7yKLVL1n6jjHbCmt .loopText,#mermaid-svg-7yKLVL1n6jjHbCmt .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-7yKLVL1n6jjHbCmt .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-7yKLVL1n6jjHbCmt .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-7yKLVL1n6jjHbCmt .noteText,#mermaid-svg-7yKLVL1n6jjHbCmt .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-7yKLVL1n6jjHbCmt .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-7yKLVL1n6jjHbCmt .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-7yKLVL1n6jjHbCmt .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-7yKLVL1n6jjHbCmt .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt .section{stroke:none;opacity:0.2}#mermaid-svg-7yKLVL1n6jjHbCmt .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-7yKLVL1n6jjHbCmt .section2{fill:#fff400}#mermaid-svg-7yKLVL1n6jjHbCmt .section1,#mermaid-svg-7yKLVL1n6jjHbCmt .section3{fill:#fff;opacity:0.2}#mermaid-svg-7yKLVL1n6jjHbCmt .sectionTitle0{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .sectionTitle1{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .sectionTitle2{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .sectionTitle3{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-7yKLVL1n6jjHbCmt .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt .grid path{stroke-width:0}#mermaid-svg-7yKLVL1n6jjHbCmt .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-7yKLVL1n6jjHbCmt .task{stroke-width:2}#mermaid-svg-7yKLVL1n6jjHbCmt .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt .taskText:not([font-size]){font-size:11px}#mermaid-svg-7yKLVL1n6jjHbCmt .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-7yKLVL1n6jjHbCmt .task.clickable{cursor:pointer}#mermaid-svg-7yKLVL1n6jjHbCmt .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-7yKLVL1n6jjHbCmt .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-7yKLVL1n6jjHbCmt .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-7yKLVL1n6jjHbCmt .taskText0,#mermaid-svg-7yKLVL1n6jjHbCmt .taskText1,#mermaid-svg-7yKLVL1n6jjHbCmt .taskText2,#mermaid-svg-7yKLVL1n6jjHbCmt .taskText3{fill:#fff}#mermaid-svg-7yKLVL1n6jjHbCmt .task0,#mermaid-svg-7yKLVL1n6jjHbCmt .task1,#mermaid-svg-7yKLVL1n6jjHbCmt .task2,#mermaid-svg-7yKLVL1n6jjHbCmt .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-7yKLVL1n6jjHbCmt .taskTextOutside0,#mermaid-svg-7yKLVL1n6jjHbCmt .taskTextOutside2{fill:#000}#mermaid-svg-7yKLVL1n6jjHbCmt .taskTextOutside1,#mermaid-svg-7yKLVL1n6jjHbCmt .taskTextOutside3{fill:#000}#mermaid-svg-7yKLVL1n6jjHbCmt .active0,#mermaid-svg-7yKLVL1n6jjHbCmt .active1,#mermaid-svg-7yKLVL1n6jjHbCmt .active2,#mermaid-svg-7yKLVL1n6jjHbCmt .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-7yKLVL1n6jjHbCmt .activeText0,#mermaid-svg-7yKLVL1n6jjHbCmt .activeText1,#mermaid-svg-7yKLVL1n6jjHbCmt .activeText2,#mermaid-svg-7yKLVL1n6jjHbCmt .activeText3{fill:#000 !important}#mermaid-svg-7yKLVL1n6jjHbCmt .done0,#mermaid-svg-7yKLVL1n6jjHbCmt .done1,#mermaid-svg-7yKLVL1n6jjHbCmt .done2,#mermaid-svg-7yKLVL1n6jjHbCmt .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-7yKLVL1n6jjHbCmt .doneText0,#mermaid-svg-7yKLVL1n6jjHbCmt .doneText1,#mermaid-svg-7yKLVL1n6jjHbCmt .doneText2,#mermaid-svg-7yKLVL1n6jjHbCmt .doneText3{fill:#000 !important}#mermaid-svg-7yKLVL1n6jjHbCmt .crit0,#mermaid-svg-7yKLVL1n6jjHbCmt .crit1,#mermaid-svg-7yKLVL1n6jjHbCmt .crit2,#mermaid-svg-7yKLVL1n6jjHbCmt .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-7yKLVL1n6jjHbCmt .activeCrit0,#mermaid-svg-7yKLVL1n6jjHbCmt .activeCrit1,#mermaid-svg-7yKLVL1n6jjHbCmt .activeCrit2,#mermaid-svg-7yKLVL1n6jjHbCmt .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-7yKLVL1n6jjHbCmt .doneCrit0,#mermaid-svg-7yKLVL1n6jjHbCmt .doneCrit1,#mermaid-svg-7yKLVL1n6jjHbCmt .doneCrit2,#mermaid-svg-7yKLVL1n6jjHbCmt .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-7yKLVL1n6jjHbCmt .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-7yKLVL1n6jjHbCmt .milestoneText{font-style:italic}#mermaid-svg-7yKLVL1n6jjHbCmt .doneCritText0,#mermaid-svg-7yKLVL1n6jjHbCmt .doneCritText1,#mermaid-svg-7yKLVL1n6jjHbCmt .doneCritText2,#mermaid-svg-7yKLVL1n6jjHbCmt .doneCritText3{fill:#000 !important}#mermaid-svg-7yKLVL1n6jjHbCmt .activeCritText0,#mermaid-svg-7yKLVL1n6jjHbCmt .activeCritText1,#mermaid-svg-7yKLVL1n6jjHbCmt .activeCritText2,#mermaid-svg-7yKLVL1n6jjHbCmt .activeCritText3{fill:#000 !important}#mermaid-svg-7yKLVL1n6jjHbCmt .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-7yKLVL1n6jjHbCmt g.classGroup text .title{font-weight:bolder}#mermaid-svg-7yKLVL1n6jjHbCmt g.clickable{cursor:pointer}#mermaid-svg-7yKLVL1n6jjHbCmt g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-7yKLVL1n6jjHbCmt g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-7yKLVL1n6jjHbCmt .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-7yKLVL1n6jjHbCmt .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-7yKLVL1n6jjHbCmt .dashed-line{stroke-dasharray:3}#mermaid-svg-7yKLVL1n6jjHbCmt #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt .commit-id,#mermaid-svg-7yKLVL1n6jjHbCmt .commit-msg,#mermaid-svg-7yKLVL1n6jjHbCmt .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-7yKLVL1n6jjHbCmt g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-7yKLVL1n6jjHbCmt g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-7yKLVL1n6jjHbCmt g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-7yKLVL1n6jjHbCmt .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-7yKLVL1n6jjHbCmt .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-7yKLVL1n6jjHbCmt .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-7yKLVL1n6jjHbCmt .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-7yKLVL1n6jjHbCmt .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-7yKLVL1n6jjHbCmt .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-7yKLVL1n6jjHbCmt .edgeLabel text{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-7yKLVL1n6jjHbCmt .node circle.state-start{fill:black;stroke:black}#mermaid-svg-7yKLVL1n6jjHbCmt .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-7yKLVL1n6jjHbCmt #statediagram-barbEnd{fill:#9370db}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-state .divider{stroke:#9370db}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-7yKLVL1n6jjHbCmt .note-edge{stroke-dasharray:5}#mermaid-svg-7yKLVL1n6jjHbCmt .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-7yKLVL1n6jjHbCmt .error-icon{fill:#522}#mermaid-svg-7yKLVL1n6jjHbCmt .error-text{fill:#522;stroke:#522}#mermaid-svg-7yKLVL1n6jjHbCmt .edge-thickness-normal{stroke-width:2px}#mermaid-svg-7yKLVL1n6jjHbCmt .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-7yKLVL1n6jjHbCmt .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-7yKLVL1n6jjHbCmt .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-7yKLVL1n6jjHbCmt .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-7yKLVL1n6jjHbCmt .marker{fill:#333}#mermaid-svg-7yKLVL1n6jjHbCmt .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-7yKLVL1n6jjHbCmt {color: rgba(0, 0, 0, 0.75);font: ;} PhoneWindowManager SystemUI WindowManagerService setSystemUiVisibility(int flag ...) statusBarVisibilityChanged(int flag) adjustSystemUiVisibilityLw(int flag) PhoneWindowManager SystemUI WindowManagerService

关键函数

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

//顾名思义, 状态栏的控制器与导航栏的控制器, 设置显示/隐藏, 或临时显示都需要它private final StatusBarController mStatusBarController = new StatusBarController();private final BarController mNavigationBarController = new BarController("NavigationBar",View.NAVIGATION_BAR_TRANSIENT,View.NAVIGATION_BAR_UNHIDE,View.NAVIGATION_BAR_TRANSLUCENT,StatusBarManager.WINDOW_NAVIGATION_BAR,WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,View.NAVIGATION_BAR_TRANSPARENT);//WindowManagerService调用@Overridepublic int adjustSystemUiVisibilityLw(int visibility) {mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);// Reset any bits in mForceClearingStatusBarVisibility that// are now clear.mResettingSystemUiFlags &= visibility;// Clear any bits in the new visibility that are currently being// force cleared, before reporting it.return visibility & ~mResettingSystemUiFlags& ~mForceClearedSystemUiFlags;}//更新FLAG用, 比如, 会获取APP的指定FLAG, 再与前面的控制器交互并更新当前的系统FLAGprivate int updateSystemUiVisibilityLw() {// If there is no window focused, there will be nobody to handle the events// anyway, so just hang on in whatever state we're in until things settle down.WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow: mTopFullscreenOpaqueWindowState;if (winCandidate == null) {return 0;}if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {// The immersive mode confirmation should never affect the system bar visibility,// otherwise it will unhide the navigation bar and hide itself.winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;if (winCandidate == null) {return 0;}}final WindowState win = winCandidate;if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {// We are updating at a point where the keyguard has gotten// focus, but we were last in a state where the top window is// hiding it.  This is probably because the keyguard as been// shown while the top window was displayed, so we want to ignore// it here because this is just a very transient change and it// will quickly lose focus once it correctly gets hidden.return 0;}int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)& ~mResettingSystemUiFlags& ~mForceClearedSystemUiFlags;if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);}final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);final int diff = visibility ^ mLastSystemUiFlags;final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu&& mFocusedApp == win.getAppToken()&& mLastNonDockedStackBounds.equals(mNonDockedStackBounds)&& mLastDockedStackBounds.equals(mDockedStackBounds)) {return 0;}mLastSystemUiFlags = visibility;mLastFullscreenStackSysUiFlags = fullscreenVisibility;mLastDockedStackSysUiFlags = dockedVisibility;mLastFocusNeedsMenu = needsMenu;mFocusedApp = win.getAppToken();final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);final Rect dockedStackBounds = new Rect(mDockedStackBounds);mHandler.post(new Runnable() {@Overridepublic void run() {StatusBarManagerInternal statusbar = getStatusBarManagerInternal();if (statusbar != null) {//传递给SystemUIstatusbar.setSystemUiVisibility(visibility, fullscreenVisibility,dockedVisibility, 0xffffffff, fullscreenStackBounds,dockedStackBounds, win.toString());statusbar.topAppWindowChanged(needsMenu);}}});return diff;}private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen? mStatusBar: opaqueOrDimming;if (statusColorWin != null) {if (statusColorWin == opaque) {// If the top fullscreen-or-dimming window is also the top fullscreen, respect// its light flag.vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)& View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;} else if (statusColorWin != null && statusColorWin.isDimming()) {// Otherwise if it's dimming, clear the light flag.vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;}}return vis;}private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);final boolean freeformStackVisible =mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();// We need to force system bars when the docked stack is visible, when the freeform stack// is visible but also when we are resizing for the transitions when docked stack// visibility changes.mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;// apply translucent bar vis flagsWindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen? mStatusBar: mTopFullscreenOpaqueWindowState;vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);final int dockedVis = mStatusBarController.applyTranslucentFlagLw(mTopDockedOpaqueWindowState, 0, 0);final boolean fullscreenDrawsStatusBarBackground =(drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)&& (vis & View.STATUS_BAR_TRANSLUCENT) == 0)|| forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);final boolean dockedDrawsStatusBarBackground =(drawsSystemBarBackground(mTopDockedOpaqueWindowState)&& (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)|| forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);// prevent status bar interaction from clearing certain flagsint type = win.getAttrs().type;boolean statusBarHasFocus = type == TYPE_STATUS_BAR;if (statusBarHasFocus && !isStatusBarKeyguard()) {int flags = View.SYSTEM_UI_FLAG_FULLSCREEN| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_IMMERSIVE| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;if (mHideLockScreen) {flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;}vis = (vis & ~flags) | (oldVis & flags);}if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {vis |= View.STATUS_BAR_TRANSPARENT;vis &= ~View.STATUS_BAR_TRANSLUCENT;} else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)|| forceOpaqueStatusBar) {vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);}vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);// update status barboolean immersiveSticky =(vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;final boolean hideStatusBarWM =mTopFullscreenOpaqueWindowState != null&& (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)& WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;final boolean hideStatusBarSysui =(vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;final boolean hideNavBarSysui =(vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;final boolean transientStatusBarAllowed = mStatusBar != null&& (statusBarHasFocus || (!mForceShowSystemBars&& (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));final boolean transientNavBarAllowed = mNavigationBar != null&& !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;final long now = SystemClock.uptimeMillis();final boolean pendingPanic = mPendingPanicGestureUptime != 0&& now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {// The user performed the panic gesture recently, we're about to hide the bars,// we're no longer on the Keyguard and the screen is ready. We can now request the bars.mPendingPanicGestureUptime = 0;mStatusBarController.showTransient();if (!isNavBarEmpty(vis)) {mNavigationBarController.showTransient();}}final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()&& !transientStatusBarAllowed && hideStatusBarSysui;final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()&& !transientNavBarAllowed;if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {// clear the clearable flags insteadclearClearableFlagsLw();vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;}final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;final boolean navAllowedHidden = immersive || immersiveSticky;if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())> windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {// We can't hide the navbar from this window otherwise the input consumer would not get// the input events.vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);}vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);// update navigation barboolean oldImmersiveMode = isImmersiveMode(oldVis);boolean newImmersiveMode = isImmersiveMode(vis);if (win != null && oldImmersiveMode != newImmersiveMode) {final String pkg = win.getOwningPackage();mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));}vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);return vis;}

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

    //SystemUI中处理由PWS传过来的FLAG.@Override // CommandQueuepublic void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {final int oldVal = mSystemUiVisibility;final int newVal = (oldVal&~mask) | (vis&mask);final int diff = newVal ^ oldVal;if (true) Log.d(TAG, String.format("setSystemUiVisibility vis=%s mask=%s oldVal=%s newVal=%s diff=%s",Integer.toHexString(vis), Integer.toHexString(mask),Integer.toHexString(oldVal), Integer.toHexString(newVal),Integer.toHexString(diff)));boolean sbModeChanged = false;if (diff != 0) {mSystemUiVisibility = newVal;// update low profileif ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {setAreThereNotifications();}// ready to unhideif ((vis & View.STATUS_BAR_UNHIDE) != 0) {mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;mNoAnimationOnNextBarModeChange = true;}// update status bar modefinal int sbMode = computeBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(),View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT,View.STATUS_BAR_TRANSPARENT);// update navigation bar modefinal int nbMode = mNavigationBarView == null ? -1 : computeBarMode(oldVal, newVal, mNavigationBarView.getBarTransitions(),View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,View.NAVIGATION_BAR_TRANSPARENT);sbModeChanged = sbMode != -1;final boolean nbModeChanged = nbMode != -1;boolean checkBarModes = false;if (sbModeChanged && sbMode != mStatusBarMode) {mStatusBarMode = sbMode;checkBarModes = true;}if (nbModeChanged && nbMode != mNavigationBarMode) {mNavigationBarMode = nbMode;checkBarModes = true;}if (checkBarModes) {checkBarModes();}if (sbModeChanged || nbModeChanged) {// update transient bar autohideif (mStatusBarMode == MODE_SEMI_TRANSPARENT || mNavigationBarMode == MODE_SEMI_TRANSPARENT) {scheduleAutohide();} else {cancelAutohide();}}if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) {mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;}//变更新, 传递新的FLAG给WMS.// send updated sysui visibility to window managernotifyUiVisibilityChanged(mSystemUiVisibility);}mLightStatusBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode);}

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    @Overridepublic void statusBarVisibilityChanged(int visibility) {Log.d(TAG, "statusBarVisibilityChanged 0x" + Integer.toHexString(visibility));if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)!= PackageManager.PERMISSION_GRANTED) {throw new SecurityException("Caller does not hold permission "+ android.Manifest.permission.STATUS_BAR);}synchronized (mWindowMap) {mLastStatusBarVisibility = visibility;//mPolicy == PhoneWindowManagervisibility = mPolicy.adjustSystemUiVisibilityLw(visibility);updateStatusBarVisibilityLocked(visibility);}}

一些常量

frameworks/base/core/java/android/view/View.java

public static final int STATUS_BAR_UNHIDE     = 0x10000000;
public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;public static final int STATUS_BAR_TRANSIENT     = 0x04000000;
public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
public static final int SYSTEM_UI_FLAG_IMMERSIVE       = 0x00000800;
public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY= 0x00001000;
public static final int NAVIGATION_BAR_TRANSPARENT     = 0x00008000;public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE          = 0x00000100;
public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN      = 0x00000400;public static final int STATUS_BAR_TRANSPARENT = 0x0000008;

如前面在PhoneStatusBar中打印statusBarVisibilityChanged 0x的16进制字符串.
如:

16进制值 FLAGS
0x0C0000000 STATUS_BAR_TRANSIENT + NAVIGATION_BAR_TRANSIENT
0x9f0a SYSTEM_UI_FLAG_IMMERSIVE_STICKY+NAVIGATION_BAR_TRANSPARENT+SYSTEM_UI_FLAG_IMMERSIVE+SYSTEM_UI_FLAG_LAYOUT_STABLE+SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION+SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN+SYSTEM_UI_FLAG_HIDE_NAVIGATION +STATUS_BAR_TRANSPARENT
  • 隐藏->显示:
    D/PhoneStatusBar: setSystemUiVisibility vis=3c009f0f mask=ffffffff oldVal=9f0f newVal=3c009f0f diff=3c000000

  • 显示->隐藏:
    D/PhoneStatusBar: setSystemUiVisibility vis=9f0f mask=ffffffff oldVal=c009f0f newVal=9f0f diff=c000000

一些干货

  • 3秒的自动隐藏时间:

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

    //3秒后自动隐藏private static final long AUTOHIDE_TIMEOUT_MS = 3000;private void scheduleAutohide() {cancelAutohide();mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS);}
  • 隐藏/显示动画
    首先找出动画是SystemUI自己执行还是由WMS去执行, 答案是WMS, 看下打印出来的堆栈信息:
2021-09-08 18:44:51.850 467-1102/system_process W/System.err:     at com.android.server.wm.WindowStateAnimator.setAnimation(WindowStateAnimator.java:275)
2021-09-08 18:44:51.850 467-1102/system_process W/System.err:     at com.android.server.wm.WindowStateAnimator.setAnimation(WindowStateAnimator.java:296)
2021-09-08 18:44:51.852 467-1102/system_process W/System.err:     at com.android.server.wm.WindowStateAnimator.applyAnimationLocked(WindowStateAnimator.java:1938)
2021-09-08 18:44:51.852 467-1102/system_process W/System.err:     at com.android.server.wm.WindowState.showLw(WindowState.java:1926)
2021-09-08 18:44:51.852 467-1102/system_process W/System.err:     at com.android.server.wm.WindowState.showLw(WindowState.java:1890)
2021-09-08 18:44:51.852 467-1102/system_process W/System.err:     at com.android.server.policy.BarController.setBarShowingLw(BarController.java:151)
2021-09-08 18:44:51.853 467-1102/system_process W/System.err:     at com.android.server.policy.BarController.adjustSystemUiVisibilityLw(BarController.java:116)
2021-09-08 18:44:51.853 467-1102/system_process W/System.err:     at com.android.server.policy.PhoneWindowManager.adjustSystemUiVisibilityLw(PhoneWindowManager.java:4124)
2021-09-08 18:44:51.853 467-1102/system_process W/System.err:     at com.android.server.wm.WindowManagerService.statusBarVisibilityChanged(WindowManagerService.java:10951)
  • 动画资源
    函数有对状态栏和导航栏对应进出资源的判断.

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

/** {@inheritDoc} */
@Override
public int selectAnimationLw(WindowState win, int transit) {if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win+ ": transit=" + transit);if (win == mStatusBar) {boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;if (transit == TRANSIT_EXIT|| transit == TRANSIT_HIDE) {return isKeyguard ? -1 : R.anim.dock_top_exit;} else if (transit == TRANSIT_ENTER|| transit == TRANSIT_SHOW) {return isKeyguard ? -1 : R.anim.dock_top_enter;}} else if (win == mNavigationBar) {if (win.getAttrs().windowAnimations != 0) {return 0;}// This can be on either the bottom or the right or the left.if (mNavigationBarPosition == NAV_BAR_BOTTOM) {if (transit == TRANSIT_EXIT|| transit == TRANSIT_HIDE) {if (isKeyguardShowingAndNotOccluded()) {return R.anim.dock_bottom_exit_keyguard;} else {return R.anim.dock_bottom_exit;}} else if (transit == TRANSIT_ENTER|| transit == TRANSIT_SHOW) {return R.anim.dock_bottom_enter;}} else if (mNavigationBarPosition == NAV_BAR_RIGHT) {if (transit == TRANSIT_EXIT|| transit == TRANSIT_HIDE) {return R.anim.dock_right_exit;} else if (transit == TRANSIT_ENTER|| transit == TRANSIT_SHOW) {return R.anim.dock_right_enter;}} else if (mNavigationBarPosition == NAV_BAR_LEFT) {if (transit == TRANSIT_EXIT|| transit == TRANSIT_HIDE) {return R.anim.dock_left_exit;} else if (transit == TRANSIT_ENTER|| transit == TRANSIT_SHOW) {return R.anim.dock_left_enter;}}} else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {return selectDockedDividerAnimationLw(win, transit);}if (transit == TRANSIT_PREVIEW_DONE) {if (win.hasAppShownWindows()) {if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");return com.android.internal.R.anim.app_starting_exit;}} else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen&& transit == TRANSIT_ENTER) {// Special case: we are animating in a dream, while the keyguard// is shown.  We don't want an animation on the dream, because// we need it shown immediately with the keyguard animating away// to reveal it.return -1;}return 0;
}
  • 在后续一些定制修改中, 强制修改了FLAG让状态栏一直显示.
    在全屏应用下, 系统会再次使StatusBar隐藏, 原因在于layout完成后,会再确认顶层应用窗口是否全屏, 并对应设置Window是否显示, 此过程无动画
2021-09-09 18:05:05.679 449-562/system_process W/System.err:     at com.android.server.policy.BarController.updateStateLw(BarController.java:194)
2021-09-09 18:05:05.680 449-562/system_process W/System.err:     at com.android.server.policy.BarController.setBarShowingLw(BarController.java:166)
2021-09-09 18:05:05.680 449-562/system_process W/System.err:     at com.android.server.policy.PhoneWindowManager.finishPostLayoutPolicyLw(PhoneWindowManager.java:5511)
2021-09-09 18:05:05.680 449-562/system_process W/System.err:     at com.android.server.wm.WindowSurfacePlacer.applySurfaceChangesTransaction(WindowSurfacePlacer.java:674)
2021-09-09 18:05:05.680 449-562/system_process W/System.err:     at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementInner(WindowSurfacePlacer.java:320)
2021-09-09 18:05:05.680 449-562/system_process W/System.err:     at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:235)
2021-09-09 18:05:05.680 449-562/system_process W/System.err:     at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:184)

finishPostLayoutPolicyLw中调用setBarShowingLw, 把状态栏隐藏了, 若需保持状态栏一直显示, 需处理这部分代码

mStatusBarController.setBarShowingLw(false);
  • 多使用dumpsys
    dumpsys window
//实时查看服务的变量状态
mOrientationSensorEnabled=truemOverscanScreen=(0,0) 1920x1080mRestrictedOverscanScreen=(0,0) 1920x1080mUnrestrictedScreen=(0,0) 1920x1080mRestrictedScreen=(0,0) 1920x1080mStableFullscreen=(0,0)-(1920,1024)mStable=(0,24)-(1920,1024)mSystem=(0,0)-(1920,1080)mCur=(0,24)-(1920,1080)mContent=(0,24)-(1920,1080)mVoiceContent=(0,24)-(1920,1080)mDock=(0,24)-(1920,1080)//状态栏被mStatusBarController.setBarShowingLw(false);隐藏时:
Window #7 Window{1633372 u0 StatusBar}:mDisplayId=0 stackId=0 mSession=Session{f3c2053 644:u0a10018} mClient=android.os.BinderProxy@236987dmOwnerUid=10018 mShowToOwnerOnly=false package=com.android.systemui appop=NONEmAttrs=WM.LayoutParams{(0,0)(fillx24) taskId=-1 gr=#30 sim=#10 ty=2000 fl=#81840048 fmt=-3 vsysui=0x600}Requested w=1920 h=24 mLayoutSeq=85mPolicyVisibility=false mPolicyVisibilityAfterAnim=false mAppOpVisibility=true mAttachedHidden=false
mPermanentlyHidden=falsemHasSurface=true mShownPosition=[0,0] isReadyForDisplay()=false hasSavedSurface()=false mWindowRemovalAllowed=falseWindowStateAnimator{7a4071f StatusBar}:Surface: shown=false layer=161000 alpha=1.0 rect=(0.0,0.0) 1920.0 x 24.0
----------------------------------
//状态栏显示时
Window #5 Window{1633372 u0 StatusBar}:mDisplayId=0 stackId=0 mSession=Session{f3c2053 644:u0a10018} mClient=android.os.BinderProxy@236987dmOwnerUid=10018 mShowToOwnerOnly=false package=com.android.systemui appop=NONEmAttrs=WM.LayoutParams{(0,0)(fillx24) taskId=-1 gr=#30 sim=#10 ty=2000 fl=#81840048 fmt=-3 vsysui=0x600}Requested w=1920 h=24 mLayoutSeq=163mHasSurface=true mShownPosition=[0,0] isReadyForDisplay()=true hasSavedSurface()=false mWindowRemovalAllowed=falseWindowStateAnimator{7a4071f StatusBar}:mAnimating=false mLocalAnimating=false mAnimationIsEntrance=true mAnimation=null mStackClip=1Surface: shown=true layer=161000 alpha=1.0 rect=(0.0,0.0) 1920.0 x 24.0------------------------------------------------------
//状态栏隐藏动画过程
Window #5 Window{16f510e u0 StatusBar}:mDisplayId=0 stackId=0 mSession=Session{5e171f4 632:u0a10018} mClient=android.os.BinderProxy@3e87b09mOwnerUid=10018 mShowToOwnerOnly=false package=com.android.systemui appop=NONEmAttrs=WM.LayoutParams{(0,0)(fillx24) taskId=-1 gr=#30 sim=#10 ty=2000 fl=#81840048 fmt=-3 vsysui=0x600}Requested w=1920 h=24 mLayoutSeq=69mPolicyVisibility=true mPolicyVisibilityAfterAnim=false mAppOpVisibility=true mAttachedHidden=falsemPermanentlyHidden=falsemHasSurface=true mShownPosition=[0,-4] isReadyForDisplay()=true hasSavedSurface()=false mWindowRemovalAllowed=falseWindowStateAnimator{2214d2c StatusBar}:mAnimating=true mLocalAnimating=true mAnimationIsEntrance=false mAnimation=android.view.animation.AnimationSet@5de858d mStackClip=0XForm: has=true hasLocal=true {alpha=1.0 matrix=[1.0, 0.0, 0.0][0.0, 1.0, -3.5060544][0.0, 0.0, 1.0]}Surface: shown=true layer=161000 alpha=1.0 rect=(0.0,-4.0) 1920.0 x 24.0mGlobalScale=1.0 mDsDx=1.0 mDtDx=0.0 mDsDy=0.0 mDtDy=1.0
  • 修改了状态栏FLAG后, 窗口布局(大小/位置)不正确可以看看这个函数, 多打打df, vf, cf …的值

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

public void layoutWindowLw(WindowState win, WindowState attached, int width, int height) {// We've already done the navigation bar and status bar. If the status bar can receive// input, we need to layout it again to accomodate for the IME window.if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {return;}final WindowManager.LayoutParams attrs = win.getAttrs();final boolean isDefaultDisplay = win.isDefaultDisplay();final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&(win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);if (needsToOffsetInputMethodTarget) {if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");offsetInputMethodWindowLw(mLastInputMethodWindow);}final int fl = PolicyControl.getWindowFlags(win, attrs);final int pfl = attrs.privateFlags;final int sim = attrs.softInputMode;final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);final Rect pf = mTmpParentFrame;final Rect df = mTmpDisplayFrame;final Rect of = mTmpOverscanFrame;final Rect cf = mTmpContentFrame;final Rect vf = mTmpVisibleFrame;final Rect dcf = mTmpDecorFrame;final Rect sf = mTmpStableFrame;//省略N行代码.....if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()+ ": sim=#" + Integer.toHexString(sim)+ " attach=" + attached + " type=" + attrs.type+ String.format(" flags=0x%08x", fl)+ " pf=" + pf.toShortString() + " df=" + df.toShortString()+ " of=" + of.toShortString()+ " cf=" + cf.toShortString() + " vf=" + vf.toShortString()+ " dcf=" + dcf.toShortString()+ " sf=" + sf.toShortString()+ " osf=" + (osf == null ? "null" : osf.toShortString()));win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
}

扩展

Android 沉浸式状态栏

Android 7.0 SystemUI 状态/导航栏的隐藏与显示相关推荐

  1. Android 5.0状态栏和导航栏

    Material Design推出之后,app中也開始沿用这样的风格 今天来说一下状态栏颜色设置,在4.4的时候推出了透明状态栏和导航栏.在不使用第三方库的情况下,4.4还是没有全然解决存在actio ...

  2. Android 7.0 SystemUI 之启动和状态栏和导航栏简介

    Android 7.0 SystemUI 之启动和状态栏和导航栏简介 一.SystemUI 是什么 首先SystemUI 是一个系统应用,apk路径位于/system/priv-app 源码路径位于: ...

  3. Android 11.0 SystemUI导航栏固定在底部显示的修改

    目录 1.概述 2.SystemUI导航栏固定在底部显示的修改的相关代码

  4. 史上最完美的Android沉浸式状态导航栏攻略

    前言 最近我在小破站开发一款新App,叫高能链.我是一个完美主义者,所以不管对架构还是UI,我都是比较抠细节的,在状态栏和导航栏沉浸式这一块,我还是踩了挺多坑,费了挺多精力的.这次我将我踩坑,适配各机 ...

  5. android 虚拟导航监听,Android另类判断NavigationBar虚拟导航栏状态

    好久没码字了,所以出来冒个泡 一直用着华为的手机,从一开始就觉得华为的虚拟导航栏用着还是挺顺手的,后来发现越来越多的机子都开始使用起来,查看源码发现,虚拟导航栏是属于SystemUI的一部分. 再一看 ...

  6. Android 8.0 学习(26)---Android 8.0 SystemUI(一)

    Android 8.0 SystemUI(一):图文并茂的介绍 : 文章已同步更新至微信公众号:猿湿Xoong 我擅长什么? 当我想到这个这个问题的时候,脑子里是一片空白的:哎呀,我什么都知道点,可是 ...

  7. [高通SDM450][Android9.0]动态控制虚拟导航栏显示与隐藏

    文章目录 开发平台基本信息 问题描述 解决方法 开发平台基本信息 芯片: SDM450 版本: Android 9.0 kernel: msm-4.9 问题描述 虚拟导航栏原生默认是显示的,但是,作为 ...

  8. (2019年10月更新) Android 最全的底部导航栏实现方法

    本文(争取做到)Android 最全的底部导航栏实现方法. 现在写了4个主要方法. 官方方法. 官方的 BottomNavigationActivity 使用Android studio 新建一个工程 ...

  9. [九鼎RK3399Pro] Android 8.1定制系统导航栏和状态栏显示和隐藏可控制

    我们的app跑在RK3399Pro上面,是放在一个公共场合使用,所以把底部的 返回,HOME,MENU键都隐藏掉,并且上部导航栏下拉功能也要取消. 代码我是参考Firefly的代码写的. 实现了一下功 ...

最新文章

  1. 修复Long类型太长转为JSON格式的时候出错的问题
  2. redis的五种存储类型的具体用法
  3. 恢复linux里被误删除的文件
  4. 一位大牛的JAVA学习资料
  5. IMYAOPTableView 源码学习笔记
  6. 【WC2014】紫荆花之恋【替罪羊思想】【动态点分树】【替罪羊树】
  7. BilibilivideoDownload下载器
  8. ES6/04/严格模式,开启严格模式,严格模式与普通模式对比发生了那些变化,高阶函数,闭包函数,递归函数,递归实例(1,阶乘,2,斐波那契数列,3,根据id返回对应数据对象),浅拷贝和深拷贝
  9. 大学计算机张青答案,《大学计算机Ⅰ》实验报告实验一1
  10. 想创业?从学会需求谈判开始
  11. strike F1 to retry boot,F2 for setup utility
  12. 米家扫地机器人按键没反应_小米扫地机系统重置键在哪?
  13. 推荐个不错的 Word 全文翻译和压缩工具!
  14. 18. --plic--=--ply--=--pli--=--ple--=--plex--=--plo-- to fold 倍,重,折叠 (词19、20)
  15. 一些事,只配当回忆.一些人,只能做过客。既不回头 何必不忘 既然无缘 何必誓言 。这个世界.那么脏.谁有资格.说悲伤。...
  16. DONT_TOUCH约束
  17. CSS3 媒体查询(media)与 Viewport
  18. 【高级篇 / System】(7.0) ❀ 07. HA 下配置核心交换机 (下) ❀ FortiGate 防火墙
  19. html游戏让目标人物移动,如何用html5编写鼠标事件与游戏人物移动
  20. Reso | Noise 网易云音乐插件

热门文章

  1. luliyu-python-day19
  2. 白盒测试----六种覆盖方法
  3. c语言文本写入结构体乱码
  4. 数据结构——二叉树的递归遍历算法与非递归遍历算法+层次遍历算法
  5. 编程基础之循环基础——多边形内角和;
  6. 前端开发的一些插件汇总
  7. kali Linux开启ssh服务
  8. redis调用lua脚本注意事项
  9. 一年中最后一个月的最后一天说说_每个月的最后一天说说一个月结束的说说
  10. 新概念 Lesson 6 Is this your shirt 所有格、祈使句