需求描述
基于 Android 14 平台,在应用界面中默认使用上滑手势会返回桌面,某些应用要求不能返回到桌面,需要屏蔽上滑手势。
需求分析
我们知道手势导航的底部导航横线的逻辑是在 SystemUI 的 NavigationBarView -> NavigationBar -> NavigationBarController -> TaskbarDelegate 等相关的类控制,在 手势导航 中上滑手势有 2 种功能:
- 从屏幕底部向上滑动,即可进入主屏幕
- 从底部向上滑动、按住再松开,可切换应用
如果想要屏蔽,可以直接返回消费掉 InputEvent 事件,就不会走后续的流程了。我尝试在 NavigationBarView 的 onInterceptTouchEvent 返回 true,但是只屏蔽了返回 Home 的功能,最近任务还是会启动。在 TaskbarDelegate 中有设置相关的 sys ui flag 的相关逻辑,于是我们可以参考类似方案,实现类似的屏蔽效果。
- TaskbarDelegate 初始化时添加需要屏蔽上滑功能的 Activity 合集
- 创建一个监听器 TaskStackChangeListener,用于监听前台应用是否需要屏蔽,并注册监听
- 任务栈变化时候改变 SysuiFlag,如
SYSUI_STATE_OVERVIEW_DISABLED和SYSUI_STATE_HOME_DISABLED
这个方案的优点是,我们不需要去追踪复杂的输入事件流,而是直接通过官方提供的、系统级的状态标志来声明我们的意图。InputDispatcher(负责分发所有触摸事件的底层服务)会尊重这些标志,并从源头上就阻止手势的发生。
解决方案
SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
1. 添加需要屏蔽上滑功能的 Activity 合集
private final List<ComponentName> mHomeBlockingActivities = new ArrayList<>();
public TaskbarDelegate(Context context, LightBarTransitionsController.Factory lightBarTransitionsControllerFactory, StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
mLightBarTransitionsControllerFactory = lightBarTransitionsControllerFactory;
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mPipListener = (bounds) -> {
mEdgeBackGestureHandler.setPipStashExclusionBounds(bounds);
};
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mStatusBarKeyguardViewManager.setTaskbarDelegate(this);
// 添加要屏蔽的 Activity
String[] disabledActivities = mContext.getResources().getStringArray(R.array.config_blockedHomeGestureActivities);
for (String disabledActivity : disabledActivities) {
mHomeBlockingActivities.add(ComponentName.unflattenFromString(disabledActivity));
}
}
在新建的 config_blockedHomeGestureActivities 数组中添加需要屏蔽类名即可

