一、问题描述
基于 Android 14平台,导航模式选择为手势导航
,此时使用一些视频类应用时候全屏观看,应用进入沉浸模式,隐藏状态栏和导航栏,从屏幕边缘滑动时的返回手势不生效,会优先响应应用内的操作如进度条前进或后退,需要快速进行 2 次侧滑才可以返回,先调出状态栏再执行返回手势逻辑,体验不好。这类问题应该是在沉浸模式下,返回手势被屏蔽了。
二、问题分析
SystemUI中 EdgeBackGestureHandler.java
负责手势导航的触控处理,包括左右滑动的逻辑,以及返回箭头的显示和隐藏。 NavigationBarEdgePanel.java
负责绘制手势导航动画的组件。
src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
找到输入事件接收器的注册
// Register input event receiver
mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
"edge-swipe", mDisplayId);
mInputEventReceiver = new InputChannelCompat.InputEventReceiver(
mInputMonitor.getInputChannel(), Looper.getMainLooper(),
Choreographer.getInstance(), this::onInputEvent);
onInputEvent(InputEvent ev)
-> onMotionEvent(MotionEvent ev)
,在 onMotionEvent 中分析事件的具体操作,这里有个变量 mAllowGesture
,用于控制是否允许手势操作
mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed
&& (isTrackpadMultiFingerSwipe || isWithinInsets)
&& !mGestureBlockingActivityRunning
&& !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
&& (isValidTrackpadBackGesture(isTrackpadMultiFingerSwipe)
|| isWithinTouchRegion((int) ev.getX(), (int) ev.getY()));
if (mAllowGesture) {
mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
mEdgeBackPlugin.onMotionEvent(ev);
dispatchToBackAnimation(ev);
}
其中 QuickStepContract.isBackGestureDisabled(mSysUiFlags)
用于返回指定的 sysui 状态是否应禁用后退手势,找到对应的沉浸模式禁用手势的 flag
// Disable when in immersive, or the notifications are interactive
int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
三、解决方案
shared/src/com/android/systemui/shared/system/QuickStepContract.java
/**
* Returns whether the specified sysui state is such that the back gesture should be
* disabled.
*/
public static boolean isBackGestureDisabled(int sysuiStateFlags) {
// Always allow when the bouncer/global actions/voice session is showing (even on top of
// the keyguard)
if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0
|| (sysuiStateFlags & SYSUI_STATE_DIALOG_SHOWING) != 0
|| (sysuiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0) {
return false;
}
if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
}
// Disable when in immersive, or the notifications are interactive
- int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
// EdgeBackGestureHandler ignores Back gesture when SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED.
// To allow Shade to respond to Back, we're bypassing this check (behind a flag).
- if (!ALLOW_BACK_GESTURE_IN_SHADE) {
- disableFlags |= SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
- }
+ int disableFlags = SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
return (sysuiStateFlags & disableFlags) != 0;
}