Android10: 动态隐藏导航栏和状态栏总结

(1)全屏相关设置

//(1)主题添加
<item name="android:windowFullscreen">true</item>

//(2)setContentView之前添加
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);  

//(3)任意位置添加flag
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) //隐藏状态栏   
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) //显示状态栏  

//(4)通过setsystemUiVisibility添加
int uiOptions = View.SYSTEM_UI_LAYOUT_FLAGS
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;

getWindow().getDecorView().setSystemUiVisibility(uiOptions);

getWindow().setStatusBarColor(Color.TRANSPARENT);//透明状态栏
getWindow().setNavigationBarColor(Color.TRANSPARENT);  //透明导航栏

(2)部分属性解析

//默认显示状态栏和导航栏
View.SYSTEM_UI_FLAG_VISIBLE
//低调模式,隐藏不重要的状态栏图标,导航栏中相应的图标都变成了一个小点
View.SYSTEM_UI_FLAG_LOW_PROFILE
//稳定布局,需要配合SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN使用,同时设置布局的android:fitsSystemWindows属性
View.SYSTEM_UI_FLAG_LAYOUT_STABLE

//全屏显示,隐藏状态栏,点击屏幕区域不会出现,需要从状态栏位置下拉才会出现
View.SYSTEM_UI_FLAG_FULLSCREEN
//全屏显示,将布局内容拓展到导航栏和状态栏的后面,状态栏不会被隐藏覆盖,状态栏依然可见,Activity布局部分会被状态栏遮挡
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
//隐藏导航栏,点击屏幕任意区域,导航栏将重新出现,并且不会自动消失
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
//将布局内容拓展到导航栏的后面
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

//配合SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN使用,使状态栏和导航栏真正的进入沉浸模式。
//点击屏幕任意区域,不会退出全屏模式,只有用户上下拉状态栏或者导航栏时才会退出------这个属性会导致拉出后状态栏和导航栏不会被自动隐藏
View.SYSTEM_UI_FLAG_IMMERSIVE
//效果跟View.SYSTEM_UI_FLAG_IMMERSIVE一样。但是,它在全屏模式下,用户上下拉状态栏或者导航栏时,这些系统栏只是以半透明的状态显示出来,并且在一定时间后会自动消失
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY

(3)不允许上下拉出现状态栏和导航栏需求

View.SYSTEM_UI_FLAG_FULLSCREEN
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY

通过以上属性来隐藏状态栏和导航栏,发现上下拉还是会出现状态栏和导航栏,现在的需求是不要出现状态栏和导航栏。

可通过如下方式拦截:

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

interface Callbacks {
        void onSwipeFromTop();
        void onSwipeFromBottom();
        void onSwipeFromRight();
        void onSwipeFromLeft();
        void onFling(int durationMs);
        void onDown();
        void onUpOrCancel();
        void onMouseHoverAtTop();
        void onMouseHoverAtBottom();
        void onMouseLeaveFromEdge();
        void onDebug();
}

private final Callbacks mCallbacks;

SystemGesturesPointerEventListener(Context context, Handler handler, Callbacks callbacks) {
        mContext = checkNull("context", context);
        mHandler = handler;
        mCallbacks = checkNull("callbacks", callbacks);

        onConfigurationChanged();
}

public void onPointerEvent(MotionEvent event) {
        if (mGestureDetector != null && event.isTouchEvent()) {
            mGestureDetector.onTouchEvent(event);
        }
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                mSwipeFireable = true;
                mDebugFireable = true;
                mDownPointers = 0;
                captureDown(event, 0);
                if (mMouseHoveringAtEdge) {
                    mMouseHoveringAtEdge = false;
                    mCallbacks.onMouseLeaveFromEdge();
                }
                mCallbacks.onDown();
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                captureDown(event, event.getActionIndex());
                if (mDebugFireable) {
                    mDebugFireable = event.getPointerCount() < 5;
                    if (!mDebugFireable) {
                        if (DEBUG) Slog.d(TAG, "Firing debug");
                        mCallbacks.onDebug();
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mSwipeFireable) {
                    final int swipe = detectSwipe(event);
                    mSwipeFireable = swipe == SWIPE_NONE;
                    if (swipe == SWIPE_FROM_TOP) {
                        if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop");
                        mCallbacks.onSwipeFromTop();
                    } else if (swipe == SWIPE_FROM_BOTTOM) {
                        if (DEBUG) Slog.d(TAG, "Firing onSwipeFromBottom");
                        mCallbacks.onSwipeFromBottom();
                    } else if (swipe == SWIPE_FROM_RIGHT) {
                        if (DEBUG) Slog.d(TAG, "Firing onSwipeFromRight");
                        mCallbacks.onSwipeFromRight();
                    } else if (swipe == SWIPE_FROM_LEFT) {
                        if (DEBUG) Slog.d(TAG, "Firing onSwipeFromLeft");
                        mCallbacks.onSwipeFromLeft();
                    }
                }
                break;
            case MotionEvent.ACTION_HOVER_MOVE:
                if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
                    if (!mMouseHoveringAtEdge && event.getY() == 0) {
                        mCallbacks.onMouseHoverAtTop();
                        mMouseHoveringAtEdge = true;
                    } else if (!mMouseHoveringAtEdge && event.getY() >= screenHeight - 1) {
                        mCallbacks.onMouseHoverAtBottom();
                        mMouseHoveringAtEdge = true;
                    } else if (mMouseHoveringAtEdge
                            && (event.getY() > 0 && event.getY() < screenHeight - 1)) {
                        mCallbacks.onMouseLeaveFromEdge();
                        mMouseHoveringAtEdge = false;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mSwipeFireable = false;
                mDebugFireable = false;
                mCallbacks.onUpOrCancel();
                break;
            default:
                if (DEBUG) Slog.d(TAG, "Ignoring " + event);
        }
    }

可从如上回调函数位置屏蔽相关滑动事件,从而实现不在出现状态栏和导航栏

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

private final SystemGesturesPointerEventListener mSystemGestures;

mSystemGestures = new SystemGesturesPointerEventListener(mUiContext, mHandler,
                new SystemGesturesPointerEventListener.Callbacks() {

					//从上往下滑触发
                    @Override
                    public void onSwipeFromTop() {
                    	//通过包名等判断条件,屏蔽上下滑动事件,从而不出现导航栏和状态栏
                    	if(tempStatus()){
								Slog.i(TAG, "onSwipeFromTop not Status Bar");
                                return;
			   		 	}
                    }

					//从下往上滑触发
                    @Override
                    public void onSwipeFromBottom() {
                    	//通过包名等判断条件,屏蔽上下滑动事件,从而不出现导航栏和状态栏
                    	if(tempStatus()){
								Slog.i(TAG, "onSwipeFromBottom not Navigation Bar");
                                return;
			    		}
                    }

					//从右往左滑触发
                    @Override
                    public void onSwipeFromRight() {
                    }

					//从左往右滑触发
                    @Override
                    public void onSwipeFromLeft() {
                    }

                    @Override
                    public void onFling(int duration) {
                    }

                    @Override
                    public void onDebug() {
                    }
                    
                    @Override
                    public void onDown() {
                    }

                    @Override
                    public void onUpOrCancel() {
                    }

                    @Override
                    public void onMouseHoverAtTop() {
                    }

                    @Override
                    public void onMouseHoverAtBottom() {
                    }

                    @Override
                    public void onMouseLeaveFromEdge() {
                    }
                });


private boolean tempStatus(){
	int tempEnable = Settings.Global.getInt(mContext.getContentResolver(), "temp_value", 0);

	ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
	List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(1);
	String topActivityPackage = "";
	if (runningTasks != null && !runningTasks.isEmpty()) {
	    ActivityManager.RunningTaskInfo taskInfo = runningTasks.get(0);
	    topActivityPackage = taskInfo.topActivity.getPackageName();
	}
	Slog.i(TAG, "dxf_tempStatus tempEnable = "
	    + tempEnable + ", topActivityPackage = " + topActivityPackage);

	return tempEnable == 1 && "com.xxxx.xxxx".equals(topActivityPackage);
    }