Android12-手势导航失效-左右手势-上拉手势失效-解决方案-经验分享

提示:Android12-左右滑动手势导航失效-解决方案:记录一次查错经验分享

文章目录


前言-需求-问题

自己在开发项目当中,随着需求增多、改来改去的突然发现手势左右滑动导航失效了,查错验证到底哪里导致了手势导航左右滑动手势失效的问题。

解决方案思路:

  • 要么去掉需求,一个一个的来重新对接,这是常规思路、也是最搞笑思路。当然在系统开发过程中可能比较慢,要一个一个验证。但是也是最靠谱的解决方案。
  • 直接死磕问题-死磕解决方案:既然不知道哪里导致的,那就找导致问题的根本原因,结合代码直接修改,不要去分析问题原因的根源, 看是否用这个思路来解决实际问题。

但是底部导航手势是OK的,能够上划到最近历史任务界面。

实际上,自己把左右滑动手势问题解决OK了,又发现底部导航手势无用了,如下:

一、参考资料

这里结合之前总结的部分手势相关的文章,可参考,属于手势相关内容模块,可借鉴参考部分基础知识和延伸扩展知识:
MTK Android12 SystemUI 手势导航 隐藏导航栏底部布局
系统手势导航-虚拟导航切换
Android12-手势导航-三按键导航切换-三按键底部导航5秒消失功能实现
MTK - Android12 默认唯一Launcher作为HOME程序-手势导航左右滑动无效问题 : 多Launcher下,设置了默认的Launcher 下左右滑动手势无效问题

二、修改文件

java 复制代码
frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java

三、解决方案

1、解决左右滑动无效问题

java 复制代码
public void onSwipeFromLeft() {
    Log.d(TAG,"================onSwipeFromLeft==============");

    final Region excludedRegion = Region.obtain();
    synchronized (mLock) {
        mDisplayContent.calculateSystemGestureExclusion(
                excludedRegion, null /* outUnrestricted */);
        final boolean excluded =
                mSystemGestures.currentGestureStartedInRegion(excludedRegion);
        Log.d(TAG,"========mNavigationBar:"+mNavigationBar);
        Log.d(TAG,"========mNavigationBarPosition:"+mNavigationBarPosition);
        Log.d(TAG,"========NAV_BAR_LEFT:"+NAV_BAR_LEFT);
        Log.d(TAG,"========excluded:"+excluded);
        Log.d(TAG,"========mNavigationBarAlwaysShowOnSideGesture:"+mNavigationBarAlwaysShowOnSideGesture);
        if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_LEFT
                || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
            Log.d(TAG,"==============requestTransientBars(mNavigationBar)=====");
            requestTransientBars(mNavigationBar);
        }

        if (mNavigationBar != null) {
            Log.d(TAG,"================mNavigationBar != null=======requestTransientBars=====");
            requestTransientBars(mNavigationBar);
        }

        checkAltBarSwipeForTransientBars(ALT_BAR_LEFT);
    }
    excludedRegion.recycle();
}

就是在 onSwipeFromLeft方法中查错,让 requestTransientBars(mNavigationBar);能够得到执行。 如上给了日志打印,对比来看就知道为什么左右滑动无效,这就是根源。【那根源找到了,那为什么会出现这样的问题呢?: 因为屏幕我们进行了旋转,所有左右滑动位置和实际的不一致,适配下或者直接干,让requestTransientBars 方法得到执行,不要拦截掉了。】

2、解决底部导航上划手势失效问题

requestTransientBars 方法中,屏蔽掉判断条件中 return 的部分,直接屏蔽掉。

java 复制代码
 private void requestTransientBars(WindowState swipeTarget) {
        if (!mService.mPolicy.isUserSetupComplete()) {
            // Swipe-up for navigation bar is disabled during setup
            return;
        }
        final InsetsSourceProvider provider = swipeTarget.getControllableInsetProvider();
        final InsetsControlTarget controlTarget = provider != null
                ? provider.getControlTarget() : null;

        if (controlTarget == null || controlTarget == getNotificationShade()) {
            // No transient mode on lockscreen (in notification shade window).
            //  return;
        }

        final @InsetsType int restorePositionTypes =
                (controlTarget.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
                        ? Type.navigationBars() : 0)
                | (controlTarget.getRequestedVisibility(ITYPE_STATUS_BAR)
                        ? Type.statusBars() : 0)
                | (mExtraNavBarAlt != null && controlTarget.getRequestedVisibility(
                                ITYPE_EXTRA_NAVIGATION_BAR)
                        ? Type.navigationBars() : 0)
                | (mClimateBarAlt != null && controlTarget.getRequestedVisibility(
                                ITYPE_CLIMATE_BAR)
                        ? Type.statusBars() : 0);

        if (swipeTarget == mNavigationBar
                && (restorePositionTypes & Type.navigationBars()) != 0) {
            // Don't show status bar when swiping on already visible navigation bar.
            // But restore the position of navigation bar if it has been moved by the control
            // target.
          //  controlTarget.showInsets(Type.navigationBars(), false);
          //  return;
        }

        if (controlTarget.canShowTransient()) {
            // Show transient bars if they are hidden; restore position if they are visible.
            mDisplayContent.getInsetsPolicy().showTransient(SHOW_TYPES_FOR_SWIPE);
            controlTarget.showInsets(restorePositionTypes, false);
        } else {
            // Restore visibilities and positions of system bars.
			  Log.d(TAG,"=============== Restore visibilities and positions of system bars.=========");

            controlTarget.showInsets(Type.statusBars() | Type.navigationBars(), false);
            // To further allow the pull-down-from-the-top gesture to pull down the notification
            // shade as a consistent motion, we reroute the touch events here from the currently
            // touched window to the status bar after making it visible.
            if (swipeTarget == mStatusBar) {
                 final boolean transferred = mStatusBar.transferTouch();
                if (!transferred) {
                    Slog.i(TAG, "Could not transfer touch to the status bar");
                }
            }
        }
         mImmersiveModeConfirmation.confirmCurrentPrompt();
    }

四、经验分享-知识点扩充

如何实现系统默认手势导航

系统手势导航-虚拟导航切换 有相关介绍

配置文件修改-config.xml

路径:\frameworks\base\core\res\res\values\config.xml

java 复制代码
\frameworks\base\core\res\res\values\config.xml 

    <!-- Controls the navigation bar interaction mode:
         0: 3 button mode (back, home, overview buttons)
         1: 2 button mode (back, home buttons + swipe up for overview)
         2: gestures only for back, home and overview -->
    <integer name="config_navBarInteractionMode">2</integer>

配置文件-主题-修改-device.mk

路径:device/mediatek/system/common/device.mk

配置属性:ro.boot.vendor.overlay.theme=com.android.internal.systemui.navbar.gestural

ro.boot.vendor.overlay.theme-属性本质

java 复制代码
ro.boot.vendor.overlay.theme=包名
  • ro.boot.xxx:开机时 init 阶段设定,只读,用于默认启用哪个 RRO overlay 包。
  • vendor.overlay.theme:系统把它当作 "默认主题 / 导航模式 overlay" 入口。
  • 这里的值都是 SystemUI 导航栏模式专用 overlay 包名。

Android 原生 4 个标准导航 overlay

1)三按键模式(经典)

java 复制代码
ro.boot.vendor.overlay.theme=com.android.internal.systemui.navbar.threebutton
  • 对应:3 键导航(返回 + Home + 多任务)
  • config:config_navBarInteractionMode = 0
  • 屏幕底部常驻三个按钮。

2)双按键 + 上滑(旧款精简)

java 复制代码
ro.boot.vendor.overlay.theme=com.android.internal.systemui.navbar.twobutton
  • 对应:2 键(返回 + Home)+ 上滑出多任务
  • config:config_navBarInteractionMode = 1
  • 底部两个键,上滑触发 overview

3)纯手势导航

java 复制代码
ro.boot.vendor.overlay.theme=com.android.internal.systemui.navbar.gestural
  • 对应:全屏手势:左 / 右滑返回、底部上滑 Home、长上滑多任务
  • config:config_navBarInteractionMode = 2
  • 底部无常驻按键条,只有手势感应区。

4)无导航栏(部分平板 / 电视)

java 复制代码
ro.boot.vendor.overlay.theme=com.android.internal.systemui.navbar.no_navbar
  • 对应:完全不显示导航栏
  • config:内部强制隐藏 nav bar
  • 一般用于纯电视 / 投影设备。

ro.boot.vendor.overlay.theme 属性配置-对照表

属性值 导航模式 config 数值 表现
threebutton 三按键 0 常驻 3 键
twobutton 双按键 + 上滑 1 常驻 2 键
gestural 纯手势 2 无按键,全手势
no_navbar 无导航栏 - 完全隐藏

个人项目开发经验分享-如何配置属性和overlay

如上讲解了部分手势导航的知识点,那么实际开发项目中常见的两种需求:配置三按键导航(添加定制部分菜单)、配置手势导航(可能左右手势都有自己的功能定义),那么如何配置。

配置底部虚拟导航栏:

默认就是这个配置。那么不要去配置overlay属性,直接配置config.xml文件中的config_navBarInteractionMode 值为2 即可。

配置手势导航

  • 在 路径:device/mediatek/system/common/device.mk 配置属性:ro.boot.vendor.overlay.theme=com.android.internal.systemui.navbar.gestural
  • 在路径:\frameworks\base\core\res\res\values\config.xml 配置config_navBarInteractionMode 值为2
java 复制代码
\frameworks\base\core\res\res\values\config.xml 

    <!-- Controls the navigation bar interaction mode:
         0: 3 button mode (back, home, overview buttons)
         1: 2 button mode (back, home buttons + swipe up for overview)
         2: gestures only for back, home and overview -->
    <integer name="config_navBarInteractionMode">2</integer>

总结

  • 这里通过手势失效问题,给出解决方案
  • 通过手势失效,延伸了解、理解 手势和虚拟导航切换配置方案的介绍
  • 核心源码 DisplayPolicy 并没有去研究,这是一个WMS 及其重要的核心策略类,后续有机会在通过案例理解。
相关推荐
weixin_5372170616 小时前
一数资源合集
经验分享
weixin_5372170616 小时前
日语教程资源合集
经验分享
Tech-Net16 小时前
TikTok视频怎么下载?2026最新TikTok无水印下载与批量解析教程
经验分享·音视频·视频编解码·视频处理·视频下载·tiktok视频下载·tiktok视频解析
ychqsq17 小时前
29.新生活轨道
经验分享·职场和发展
上海光华专利事务所17 小时前
集团型企业的知识产权管理:多主体架构与数据隔离
经验分享
随便做点啥17 小时前
Intel Arc B60 Qwen3-Omni-30B-A3B Thinking vs Instruct 横向对比测试报告
服务器·经验分享
05候补工程师17 小时前
【线性代数】核心题型大通关:从行列式、矩阵到向量组的解题精髓与全模板总结
经验分享·笔记·线性代数·考研·矩阵
优化控制仿真模型17 小时前
【26年专四】英语专业四级TEM4历年真题及答案电子版PDF(2009-2025年)
经验分享·pdf