SystemUI导航栏

news2024/12/25 12:53:13

SystemUI导航栏

  • 1、系统中参数项
    • 1.1 相关开关属性
    • 2.2 属性设置代码
  • 2、设置中设置“三按钮”导航更新流程
    • 2.1 属性资源覆盖叠加
    • 2.2 SystemUI导航栏接收改变广播
    • 2.3 SystemUI导航栏布局更新
    • 2.4 时序图

android13-release


1、系统中参数项

1.1 相关开关属性

设置->系统->手势->系统导航->“三按钮”导航
在这里插入图片描述

  • 设置中:“三按钮”导航
    packages/apps/Settings/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
    packages/apps/Settings/res/values-zh-rCN/strings.xml
    <string name="legacy_navigation_title" msgid="7877402855994423727">"“三按钮”导航"</string>

  • 默认导航栏模式:config_navBarInteractionMode
    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">0</integer>

   <!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
        autodetected from the Configuration. -->
   <bool name="config_showNavigationBar">false</bool>
  • Settings数据库中:adb shell settings get Secure navigation_mode
    frameworks/base/core/java/android/provider/Settings.java
/**
 * Navigation bar mode.
 *  0 = 3 button
 *  1 = 2 button
 *  2 = fully gestural
 * @hide
 */
@Readable
public static final String NAVIGATION_MODE =
        "navigation_mode";
  • prop属性"qemu.hw.mainkeys":允许系统属性覆盖此设置。由仿真器使用。使用方法hasNavigationBar()
  • 导航栏高度:navigation_bar_height
    frameworks/base/core/res/res/values/dimens.xml
   <!-- Height of the bottom navigation / system bar. -->
   <dimen name="navigation_bar_height">48dp</dimen>
   <!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
   <dimen name="navigation_bar_height_landscape">48dp</dimen>

2.2 属性设置代码

设置中显示判断:

  • String NAV_BAR_MODE_3BUTTON_OVERLAY = "com.android.internal.systemui.navbar.threebutton";
    /product/overlay/NavigationBarMode3Button/NavigationBarMode3ButtonOverlay.apk
  • String NAV_BAR_MODE_2BUTTON_OVERLAY = "com.android.internal.systemui.navbar.twobutton";
    /product/overlay/NavigationBarMode2Button/NavigationBarMode2ButtonOverlay.apk
  • String NAV_BAR_MODE_GESTURAL_OVERLAY = "com.android.internal.systemui.navbar.gestural";
    /product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk

packages/apps/Settings/src/com/android/settings/gestures/SystemNavigationPreferenceController.java

static boolean isOverlayPackageAvailable(Context context, String overlayPackage) {
    try {
        return context.getPackageManager().getPackageInfo(overlayPackage, 0) != null;
    } catch (PackageManager.NameNotFoundException e) {
        // Not found, just return unavailable
        return false;
    }
}

frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java

private int mNavBarMode = NAV_BAR_MODE_3BUTTON;

mNavBarMode = mNavigationModeController.addListener(mModeChangedListener);

frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java

private int getCurrentInteractionMode(Context context) {
    int mode = context.getResources().getInteger(
            com.android.internal.R.integer.config_navBarInteractionMode);
    if (DEBUG) {
        Log.d(TAG, "getCurrentInteractionMode: mode=" + mode
                + " contextUser=" + context.getUserId());
    }
    return mode;
}

public void updateCurrentInteractionMode(boolean notify) {
    mCurrentUserContext = getCurrentUserContext();
    int mode = getCurrentInteractionMode(mCurrentUserContext);
    mUiBgExecutor.execute(() ->
        Settings.Secure.putString(mCurrentUserContext.getContentResolver(),
                Secure.NAVIGATION_MODE, String.valueOf(mode)));
    if (DEBUG) {
        Log.d(TAG, "updateCurrentInteractionMode: mode=" + mode);
        dumpAssetPaths(mCurrentUserContext);
    }

    if (notify) {
        for (int i = 0; i < mListeners.size(); i++) {
            mListeners.get(i).onNavigationModeChanged(mode);
        }
    }
}

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

if (mDisplayContent.isDefaultDisplay) {
    mHasStatusBar = true;
    mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);

    // Allow a system property to override this. Used by the emulator.
    // See also hasNavigationBar().
    String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
    if ("1".equals(navBarOverride)) {
        mHasNavigationBar = false;
    } else if ("0".equals(navBarOverride)) {
        mHasNavigationBar = true;
    }
} else {
    mHasStatusBar = false;
    mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
}

2、设置中设置“三按钮”导航更新流程

2.1 属性资源覆盖叠加

OverlayManagerService 运行时资源叠加层 (RRO)
点击设置后,导航栏模式通过 OverlayManagerService 服务对 config_navBarInteractionMode 资源进行叠加,而settings的Secure表中navigation_mode属性只是记录模式。
frameworks/base/services/core/java/com/android/server/om/OverlayManagerService.java

资源叠加主要文件:
frameworks/base/core/res/res/values/config.xml
/product/overlay/NavigationBarMode3Button/NavigationBarMode3ButtonOverlay.apk
/product/overlay/NavigationBarMode2Button/NavigationBarMode2ButtonOverlay.apk
/product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk

  • updateActivityManager(affectedPackages, userId):发送受覆盖状态更改影响的所有目标包的配置更改事件。
  • broadcastActionOverlayChanged(targets, userId):发送覆盖包已更改广播ACTION_OVERLAY_CHANGED
private void updateTargetPackagesLocked(@Nullable Set<PackageAndUser> updatedTargets) {
    if (CollectionUtils.isEmpty(updatedTargets)) {
        return;
    }
    persistSettingsLocked();
    final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(updatedTargets);
    for (int i = 0, n = userTargets.size(); i < n; i++) {
        final ArraySet<String> targets = userTargets.valueAt(i);
        final int userId = userTargets.keyAt(i);
        final List<String> affectedPackages = updatePackageManagerLocked(targets, userId);
        if (affectedPackages.isEmpty()) {
            // The package manager paths are already up-to-date.
            continue;
        }

        FgThread.getHandler().post(() -> {
            // Send configuration changed events for all target packages that have been affected
            // by overlay state changes.
            updateActivityManager(affectedPackages, userId);

            // Do not send broadcasts for all affected targets. Overlays targeting the framework
            // or shared libraries may cause too many broadcasts to be sent at once.
            broadcastActionOverlayChanged(targets, userId);
        });
    }
}

2.2 SystemUI导航栏接收改变广播

mReceiver :监听ACTION_OVERLAY_CHANGED广播
Secure.NAVIGATION_MODE:记录导航栏模式改变值
mListeners.get(i).onNavigationModeChanged(mode):通知导航栏模式改变的ModeChangedListener监听

frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java

private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (DEBUG) {
            Log.d(TAG, "ACTION_OVERLAY_CHANGED");
        }
        updateCurrentInteractionMode(true /* notify */);
    }
};

public NavigationModeController(Context context,
        DeviceProvisionedController deviceProvisionedController,
        ConfigurationController configurationController,
        @UiBackground Executor uiBgExecutor,
        DumpManager dumpManager) {
    //... ...
    IntentFilter overlayFilter = new IntentFilter(ACTION_OVERLAY_CHANGED);
    overlayFilter.addDataScheme("package");
    overlayFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);
    mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);
    //... ...
}

public void updateCurrentInteractionMode(boolean notify) {
    mCurrentUserContext = getCurrentUserContext();
    int mode = getCurrentInteractionMode(mCurrentUserContext);
    mUiBgExecutor.execute(() ->
        Settings.Secure.putString(mCurrentUserContext.getContentResolver(),
                Secure.NAVIGATION_MODE, String.valueOf(mode)));
    if (DEBUG) {
        Log.d(TAG, "updateCurrentInteractionMode: mode=" + mode);
        dumpAssetPaths(mCurrentUserContext);
    }

    if (notify) {
        for (int i = 0; i < mListeners.size(); i++) {
            mListeners.get(i).onNavigationModeChanged(mode);
        }
    }
}

2.3 SystemUI导航栏布局更新

NavigationModeController通知监听执行onNavigationModeChanged方法更新,最后 navBar.getView().updateStates()执行更新界面NavigationBarView

  • updateSlippery():更新WindowManager.LayoutParams.FLAG_SLIPERY状态,具体取决于是否启用了向上滑动,或者通知是否在未处于动画状态的情况下完全打开。如果启用了slide,触摸事件将离开导航栏窗口并进入全屏应用程序/主页窗口,如果没有,则手势离开导航栏后,导航栏将收到取消的触摸事件。
  • reloadNavIcons():重新导入导航栏相关图片资源
  • updateNavButtonIcons:更新界面导航栏图标、显示状态,及活动触摸区域

frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java

@Override
public void onNavigationModeChanged(int mode) {
    if (mNavMode == mode) {
        return;
    }
    final int oldMode = mNavMode;
    mNavMode = mode;
    updateAccessibilityButtonModeIfNeeded();

    mHandler.post(() -> {
        // create/destroy nav bar based on nav mode only in unfolded state
        if (oldMode != mNavMode) {
            updateNavbarForTaskbar();
        }
        for (int i = 0; i < mNavigationBars.size(); i++) {
            NavigationBar navBar = mNavigationBars.valueAt(i);
            if (navBar == null) {
                continue;
            }
            navBar.getView().updateStates();
        }
    });
}

frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java

public void updateStates() {
    if (mNavigationInflaterView != null) {
        // Reinflate the navbar if needed, no-op unless the swipe up state changes
        mNavigationInflaterView.onLikelyDefaultLayoutChange();
    }

    updateSlippery();
    reloadNavIcons();
    updateNavButtonIcons();
    WindowManagerWrapper.getInstance().setNavBarVirtualKeyHapticFeedbackEnabled(
            !mShowSwipeUpUi);
    getHomeButton().setAccessibilityDelegate(
            mShowSwipeUpUi ? mQuickStepAccessibilityDelegate : null);
}

2.4 时序图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1059543.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++算法 —— 动态规划(9)完全背包问题

文章目录 1、动规思路简介2、完全背包【模板】3、零钱兑换4、零钱兑换Ⅱ5、完全平方数 背包问题需要读者先明白动态规划是什么&#xff0c;理解动规的思路&#xff0c;并不能给刚接触动规的人学习。所以最好是看了之前的动规博客&#xff0c;以及01背包博客&#xff0c;才能看完…

学习C++语言可以适用于哪些方面

学习C可以让你具备开发各种类型软件和系统的能力&#xff0c;它是一种通用的、高性能的编程语言。以下是学习C的一些用途和应用领域&#xff1a; 系统开发&#xff1a;C被广泛用于操作系统、驱动程序和嵌入式系统的开发。通过学习C&#xff0c;你可以编写底层的系统代码&#x…

java大富翁

一、 概述 Java Swing大富翁游戏是一个经典的大富翁桌面游戏的简单实现&#xff0c;使用Java Swing库创建。该游戏允许玩家在一个虚拟棋盘上掷骰子&#xff0c;购买和升级属性&#xff0c;赚取租金和尽量丰富自己。这个文档说明将介绍如何安装和运行游戏&#xff0c;以及游戏规…

【C++】C++11——右值引用和移动语义、左值引用和右值引用、右值引用使用场景和意义、完美转发、新的类功能

文章目录 C115.右值引用和移动语义5.1左值引用和右值引用5.2左值引用与右值引用比较5.3右值引用使用场景和意义5.4右值引用引用左值及其一些更深入的使用场景分析5.5完美转发 6.新的类功能 C11 5.右值引用和移动语义 右值引用是C11引入的一个新特性&#xff0c;用于支持移动语义…

冯诺依曼体系结构与进程的初步理解

目录 一&#xff0c;冯诺依曼体系结构 1.是什么&#xff1f;特点 2.为什么&#xff1f; 二&#xff0c;操作系统 三&#xff0c;进程 1.什么是进程&#xff1f; 2.查看进程 3.进程的管理 4.fork()创建子进程 1.fork()简介 2.fork()干了啥 3.fork()为什么会有两个返回…

【Java】微服务——Ribbon负载均衡(跟进源码分析原理)

添加LoadBalanced注解&#xff0c;即可实现负载均衡功能&#xff0c;这是什么原理 1.负载均衡原理 SpringCloud底层其实是利用了一个名为Ribbon的组件&#xff0c;来实现负载均衡功能的。 2.源码跟踪 为什么我们只输入了service名称就可以访问了呢&#xff1f;之前还要获取…

mstsc无法保存RDP凭据, 100%生效

问题 即使如下两项都打勾&#xff0c;其还是无法保存凭据&#xff0c;特别是连接Ubuntu (freerdp server)&#xff1a; 解决方法 网上多种复杂方法&#xff0c;不生效&#xff0c;其思路是修改后台配置&#xff0c;以使mstsc跟平常一样自动记住凭据。最后&#xff0c;如下的…

Python无废话-办公自动化Excel写入操作

Python 办公自动化-Excel写入 创建并保存Excel文件 import openpyxl workbookopenpyxl.Workbook() #创建空Excel文件 sheetworkbook.active #获取活动的工作表 sheet.title“测试“ #修改sheet工作表名称为测试 workbook.save(“data\input\Test.xlsx”) #保存Excel文件 …

R中的min()函数 和max()函数

通过min()函数和max()函数产生Inf 数值空集的最小值和最大值是Inf和–Inf(按此顺序&#xff01;)这确保了传递性&#xff0c;例如min(x1&#xff0c;min(x2)) min(x1&#xff0c;x2)。对于数值x&#xff0c;每当length (x) 0时&#xff0c;max(x) - Inf和min(x) Inf(如果需…

C#餐饮收银系统

一、引言 餐饮收银系统是一种用于管理餐馆、咖啡厅、快餐店等餐饮业务的计算机化工具。它旨在简化点餐、结账、库存管理等任务&#xff0c;提高运营效率&#xff0c;增强客户体验&#xff0c;同时提供准确的财务记录。C# 餐饮收银系统是一种使用C#编程语言开发的餐饮业务管理软…

SDK Vitis记录

文章目录 SDK记录SDK中报错“undefined reference to sqrt”的解决方法通过XML文件导入工程的include路径方法说明 其他设置编译选项设置某些文件/文件夹不编译单独设置文件的编译选项 向存储区中导入/导出数据通过GUI操作使用命令行操作 产生C代码的MAP文件在Xilinx SDK 工程的…

Golang 中的调试技巧

掌握有效的策略和工具&#xff0c;实现顺畅的开发 调试是每位开发人员都必须掌握的关键技能。它是识别、隔离和解决代码库中问题的过程。在 Golang 的世界中&#xff0c;掌握有效的调试技巧可以显著提升您的开发工作流程&#xff0c;并帮助您创建更可靠和健壮的应用程序。在本…

C语言 —— 函数栈帧的创建和销毁

在我们之前学习函数的时候&#xff0c;我们可能有很多困惑? 比如: 局部变量是怎么创建的?为什么局部变量的值是随机值?函数是怎么传参的?传参的顺序是怎样的?形参和实参是什么关系?函数调用是怎么做的?函数调用是结束后怎么返回的? 那么要解决这些问题, 我们就需要知道…

Raspberry Pi 5 新平台 新芯片组

Raspberry Pi 5 的 CPU 和 GPU 性能提高了两到三倍&#xff1b;内存和 I/O 带宽大约是两倍&#xff1b;并且是首款采用英国剑桥内部设计的芯片的 Raspberry Pi 计算机&#xff0c;4GB 型号的售价为 60 美元&#xff0c;8GB 版本的售价为 80 美元 主要特点包括&#xff1a; 2.4…

Zama的fhEVM:基于全同态加密实现的隐私智能合约

1. 引言 Zama的fhEVM定位为&#xff1a; 基于全同态加密实现的隐私智能合约 解决方案 开源代码见&#xff1a; https://github.com/zama-ai/fhevm&#xff08;TypeScript Solidity&#xff09; Zama的fhEVM协议中主要包含&#xff1a; https://github.com/zama-ai/tfhe-…

Windows11+VS2022+OCCT7.6.0安装配置记录

Windows11VS2022OCCT7.6.0安装配置记录 工具及源码准备VS2022以及CMake下载OCCT源码下载第三方库 CMake修改occt_toolkit.cmake进行CMake Visual Studio环境配置配置包含目录配置库目录配置链接器设置系统环境变量配置项目调试环境环境测试 其他方法 主要参考此文&#xff0c;在…

自然语言处理的分类

动动发财的小手&#xff0c;点个赞吧&#xff01; 简介 作为理解、生成和处理自然语言文本的有效方法&#xff0c;自然语言处理&#xff08;NLP&#xff09;的研究近年来呈现出快速传播和广泛采用。鉴于 NLP 的快速发展&#xff0c;获得该领域的概述并对其进行维护是很困难的。…

Golang 语言学习 01 包含如何快速学习一门新语言

Golang方向 区块链 go服务器端 (后台流量支撑程序) 支撑主站后台流量&#xff08;排序&#xff0c;推荐&#xff0c;搜索等&#xff09;&#xff0c;提供负载均衡&#xff0c;cache&#xff0c;容错&#xff0c;按条件分流&#xff0c;统计运行指标 (qps&#xff0c; latenc…

java飞机大战

一、 概述 1.1 项目简介 本次Java课程设计是做一个飞机大战的游戏&#xff0c;应用Swing编程&#xff0c;完成一个界面简洁流畅、游戏方式简单&#xff0c;玩起来易于上手的桌面游戏。该飞机大战项目运用的主要技术即是Swing编程中的一些窗口类库、事件监听以及贴图技术。 1…

微信小程序WebSocket实现stream流式聊天对话功能

要在微信小程序实现聊天对话功能&#xff0c;回话是流式应答&#xff0c;这里使用了WebSocket技术。WebSocket大家应该都很熟悉&#xff0c;使用wx.connectSocket就可以了。这里可能需要注意下的是流式应答&#xff0c;后端如何发送&#xff0c;前端如何接收。直接上代码&#…