Android11——手势&系统导航添加

问题分析

问题:

        客户需求,底部导航栏可选隐藏与显示。

分析:

        正常来讲,Android11自带的有系统导航可选"三按钮"导航跟手势导航。打开位置有两个

1.设置——>无障碍——>系统导航

2.设置——>系统——>手势——>系统导航

可是如下图所示并未显示出来

 分析可能是布局或者是activity隐藏了,最后发现是应为自定义的overlay把他隐藏掉了,本文最后将会详细了解一下android源码的overlay

代码位置

alps/device/mediatek/vendor/common/overlay/ago/frameworks/base/core/res/res/values/config.xml  alps/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/gestures/SystemNavigationPreferenceController.java    alps/vendor/mediatek/proprietary/packages/overlay/vendor/FrameworkResOverlay/ago/res/values/config.xml

具体代码

    static boolean isGestureAvailable(Context context) {
        // Skip if the swipe up settings are not available
        if (!context.getResources().getBoolean(
                com.android.internal.R.bool.config_swipe_up_gesture_setting_available)) {
                Log.w(TAG,"lyzlyzlyz01----------------------------------------------------------------------------");
            return false;
        }

        // Skip if the recents component is not defined
        final ComponentName recentsComponentName = ComponentName.unflattenFromString(
                context.getString(com.android.internal.R.string.config_recentsComponentName));
        if (recentsComponentName == null) {
            return false;
        }

        // Skip if the overview proxy service exists
        final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
                .setPackage(recentsComponentName.getPackageName());
        if (context.getPackageManager().resolveService(quickStepIntent,
                PackageManager.MATCH_SYSTEM_ONLY) == null) {
            return false;
        }

        return true;
    }
- <bool name="config_swipe_up_gesture_setting_available">false</bool>
+ <bool name="config_swipe_up_gesture_setting_available">true</bool>

代码分析

首先找到gestures(手势)布局

alps\vendor\mediatek\proprietary\packages\apps\MtkSettings\res\xml\gestures.xml

在里面找到导航栏的布局文件

  <Preference
        android:key="gesture_system_navigation_input_summary"
        android:title="@string/system_navigation_title"
        android:fragment="com.android.settings.gestures.SystemNavigationGestureSettings"
        settings:controller="com.android.settings.gestures.SystemNavigationPreferenceController"
        settings:keywords="@string/keywords_system_navigation" />

进入controller代码查看问题,log查看发现isGestureAvailable方法中存在疑点

 if (!context.getResources().getBoolean(
                com.android.internal.R.bool.config_swipe_up_gesture_setting_available)) {
            return false;
        }

grep查询后发现

cts-15@cts-15:/code2/W869/mt6580_r_v1/alps$ cd device/
cts-15@cts-15:/code2/W869/mt6580_r_v1/alps/device$ grep "config_swipe_up_gesture_setting_available" * -rn
google/coral/overlay/frameworks/base/core/res/res/values/config.xml:268:    <bool name="config_swipe_up_gesture_setting_available">true</bool>
mediatek/build/mcs/Q0.basic_hiddenapi-stub-flags.txt:243583:Lcom/android/internal/R$bool;->config_swipe_up_gesture_setting_available:I
mediatek/vendor/common/overlay/ago/frameworks/base/core/res/res/values/config.xml:26:    <bool name="config_swipe_up_gesture_setting_available">false</bool>
cts-15@cts-15:/code2/W869/mt6580_r_v1/alps/device$ cd ../
cts-15@cts-15:/code2/W869/mt6580_r_v1/alps$ cd vendor/mediatek/
cts-15@cts-15:/code2/W869/mt6580_r_v1/alps/vendor/mediatek$ grep "config_swipe_up_gesture_setting_available" * -rn
proprietary/packages/apps/MtkSettings/src/com/android/settings/gestures/SystemNavigationPreferenceController.java:63:                com.android.internal.R.bool.config_swipe_up_gesture_setting_available)) {
proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/gestures/SystemNavigationPreferenceControllerTest.java:74:        SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_setting_available,
proprietary/packages/apps/MtkSettings/tests/robotests/src/com/android/settings/gestures/SystemNavigationPreferenceControllerTest.java:113:        SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_setting_available,
proprietary/packages/overlay/vendor/FrameworkResOverlay/ago/res/values/config.xml:27:    <bool name="config_swipe_up_gesture_setting_available">false</bool>
cts-15@cts-15:/code2/W869/mt6580_r_v1/alps/vendor/mediatek$ cd ../../
cts-15@cts-15:/code2/W869/mt6580_r_v1/alps$ cd frameworks/base/
cts-15@cts-15:/code2/W869/mt6580_r_v1/alps/frameworks/base$ grep "config_swipe_up_gesture_setting_available" * -rn
config/hiddenapi-greylist-max-o.txt:91412:Lcom/android/internal/R$bool;->config_swipe_up_gesture_setting_available:I
core/res/res/values/config.xml:3824:    <bool name="config_swipe_up_gesture_setting_available">true</bool>
core/res/res/values/symbols.xml:3574:  <java-symbol type="bool" name="config_swipe_up_gesture_setting_available" />
cts-15@cts-15:/code2/W869/mt6580_r_v1/alps/frameworks/base$ ^C

把false改为true问题解决。

overlay详解

Android Overlay是一种资源替换机制,它能在不重新打包apk的情况下,实现资源文件的替换(res目录非assert目录),Overlay又分为静态Overlay(Static Resource Overlay)与运行时Overlay(Runtime Resource Overlay),他有自己的局限性,它无法替换java文件。
Android Override是一种文件替换方式,注意是文件替换,他有自己的局限性,它无法覆盖一个APK中的某一个文件,但是可以直接覆盖APK。

我们可以将Android资源类型分为三类:

列表类型的xml资源文件,该类型的文件内部包含了多个资源项,典型的就是strings.xml,很多项目会有config.xml也大都是这种类型的文件。

值类型的xml文件,该类型的一个文件对应了一个资源项,比如layout目录下的布局文件,以及某些项目menu目录下的xml文件也大都是这种类型。

数据型资源文件,比如图片,音频,视频以及其他数据类型的文件,该类型的一个文件对应一个资源项。

在最终的安装包中第三种数据类型的资源文件会原封不动的保留。第二种值类型的xml资源文件,也会按照原有的目录结构和文件名字放入安装包中, 只是原有的xml格式会被压缩成特定的二进制流。列表型xml资源文件的内容会被全部编译到resources.arsc中。而我们的overlay就是替换resources.arsc中的资源文件

所以,一般overlay放在项目的vendor frameworks device 三个地方,编译的时候overlay会覆盖原来的资源文件。修改以前项目的修改后系统导航出现并可以正常使用。效果如下:

 

### 左右滑动返回功能的实现 在 Android 应用中,可以通过重写 `onFling` 方法或者监听手势事件来实现左右滑动返回功能。以下是具体方法: #### 使用 GestureDetector 实现手势检测 GestureDetector 是 Android 提供的手势识别工具类,能够轻松捕获用户的触摸行为并转化为特定的手势动作。 ```java import android.gesture.Gesture; import android.os.Bundle; import android.view.GestureDetector; import android.view.MotionEvent; public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener { private GestureDetector gestureDetector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化 Gesture Detector gestureDetector = new GestureDetector(this, this); } @Override public boolean onTouchEvent(MotionEvent event) { return gestureDetector.onTouchEvent(event); // 将触控事件传递给 Gesture Detector } @Override public boolean onDown(MotionEvent e) { return false; // 不需要处理按下事件 } @Override public void onShowPress(MotionEvent e) {} @Override public boolean onSingleTapUp(MotionEvent e) { return false; // 不需要处理单击事件 } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; // 不需要处理滚动事件 } @Override public void onLongPress(MotionEvent e) {} @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { try { if (e1.getX() - e2.getX() &gt; 100 &amp;&amp; Math.abs(velocityX) &gt; 800) { finish(); // 右滑返回上一页 overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right); return true; } else if (e2.getX() - e1.getX() &gt; 100 &amp;&amp; Math.abs(velocityX) &gt; 800) { onBackPressed(); // 左滑触发返回按钮逻辑 return true; } } catch (Exception exception) {} return false; } } ``` 上述代码实现了基于手势的左右滑动返回功能[^1]。当用户从屏幕右侧快速向左侧滑动时,调用 `finish()` 结束当前 Activity;而从左侧快速向右侧滑动时,则模拟点击返回键的行为。 --- #### 修改 SystemUI 实现全局手势支持 如果希望在整个系统范围内启用类似的左右滑动返回功能,可以考虑修改系统的 `SystemUI` 组件。这通常用于 ROM 定制开发场景下。通过分析和调整 `SystemGestureNavigationController.java` 或其他相关文件中的手势逻辑,即可完成全局范围内的手势配置[^2]。 --- #### 自定义手势返回 UI 效果 为了满足更高层次的需求(如仿小米或华为的手势动画),可以在现有基础上进一步优化视觉体验。例如,在手势滑动过程中动态显示半透明背景或其他过渡效果。这种定制化方案涉及对底层绘制机制的理解以及对动画框架的应用[^3]。 --- #### 利用 Keycode 模拟按键事件 另一种方式是在某些特殊情况下利用键盘输入的方式间接达到目的。比如在外围设备接入的情况下设置侧滑手势发送 `KEYCODE_BACK` 键值,并在其内部捕捉该信号从而做出相应反应[^4]。 ```java @Override public boolean dispatchKeyEvent(@NonNull final KeyEvent event) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_BACK: if (view != null) { onBackPressed(); // 调用手动退栈函数 } return true; default: return super.dispatchKeyEvent(event); } } ``` 此片段展示了如何拦截物理按键消息流以便于扩展更多交互可能性。 --- ### 总结 以上介绍了几种常见的途径去达成所描述的目标&mdash;&mdash;即让安卓程序具备响应水平方向移动进而切换视图的能力。开发者可以根据实际项目需求选取合适的技术路线加以实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值