Android11.0 导航栏添加图标截屏

news2025/4/13 7:41:52

需求: 导航栏添加截屏和电源键图标,控制截屏和用于设备重启关机功能。设置中添加延时截屏和控制截屏图标显示开关。
在这里插入图片描述

1. 导航栏添加图标

1.1 添加布局文件和图标icon

在layout目录下添加nav_power.xml和screenshot.xml文件

  • frameworks/base/packages/SystemUI/res/layout/nav_power.xml
<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.statusbar.policy.KeyButtonView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_power"
    android:layout_width="@dimen/navigation_key_width"
    android:layout_height="match_parent"
    android:layout_weight="0"
    android:scaleType="center"
    android:contentDescription="@string/accessibility_home"
    android:paddingStart="@dimen/navigation_key_padding"
    android:paddingEnd="@dimen/navigation_key_padding"
    />
  • frameworks/base/packages/SystemUI/res/layout/screenshot.xml
<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.statusbar.policy.KeyButtonView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/screenshot"
    android:layout_width="@dimen/navigation_key_width"
    android:layout_height="match_parent"
    android:layout_weight="0"
    systemui:keyCode="0"
    android:scaleType="center"
    android:contentDescription="@string/accessibility_home"
    android:paddingStart="@dimen/navigation_key_padding"
    android:paddingEnd="@dimen/navigation_key_padding"
    />

drawable目录下添加ic_sysbar_power_button.xml和ic_sysbar_screenshot_button.xml

  • frameworks/base/packages/SystemUI/res/drawable/ic_sysbar_power_button.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
  <path
      android:fillColor="?attr/singleToneColor"
      android:pathData="M11,2h2v10h-2zM18.37,5.64l-1.41,1.41c2.73,2.73 2.72,7.16 -0.01,9.89 -2.73,2.73 -7.17,2.73 -9.89,0.01 -2.73,-2.73 -2.74,-7.18 -0.01,-9.91l-1.41,-1.4c-3.51,3.51 -3.51,9.21 0.01,12.73 3.51,3.51 9.21,3.51 12.72,-0.01 3.51,-3.51 3.51,-9.2 0,-12.72z"/>
</vector>
  • frameworks/base/packages/SystemUI/res/drawable/ic_sysbar_screenshot_button.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
  <path
      android:fillColor="?attr/singleToneColor"
      android:pathData="M17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,21L7,21v-1h10v1zM17,18L7,18L7,6h10v12zM17,4L7,4L7,3h10v1zM9.5,8.5L12,8.5L12,7L8,7v4h1.5zM12,17h4v-4h-1.5v2.5L12,15.5z"/>
</vector>

1.2 加载布局

  • frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
public static final String HOME = "home";
// add start
public static final String SCREENSHOT = "screenshot";
public static final String NAV_POWER = "nav_power";
// end

// 获取默认布局资源配置,关系到下一步修改图标显示位置顺序
protected String getDefaultLayout() {
    final int defaultResource = QuickStepContract.isGesturalMode(mNavBarMode)
            ? R.string.config_navBarLayoutHandle
            : mOverviewProxyService.shouldShowSwipeUpUI()
                    ? R.string.config_navBarLayoutQuickstep
                    : R.string.config_navBarLayout;
    return getContext().getString(defaultResource);
}

...

private View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater) {
        View v = null;
        ...
        if (HOME.equals(button)) {
            v = inflater.inflate(R.layout.home, parent, false);
        // add start
        } else if (SCREENSHOT.equals(button)) {
            v = inflater.inflate(R.layout.screenshot, parent, false);
        } else if (NAV_POWER.equals(button)) {
            v = inflater.inflate(R.layout.nav_power, parent, false);
        }
        // end

1.3 控制导航栏按键显示位置

  • frameworks/base/packages/SystemUI/res/values-sw372dp/config.xml
<string name="config_navBarLayout" translatable="false">left[.25W],screenshot[.5WC],back[.5WC];home;recent[.5WC],nav_power[.5WC],right[.25W]</string>

这个根据设备的分辨率来修改,有可能需要修改其他目录下的config,搜索config_navBarLayout

1.4 添加的按键设置图标

  • frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
private KeyButtonDrawable mBackIcon;
private KeyButtonDrawable mHomeDefaultIcon;
// add start
private KeyButtonDrawable mScreenshotIcon;
private KeyButtonDrawable mNavPowerIcon;
// end 

...

public NavigationBarView(Context context, AttributeSet attrs) {
    super(context, attrs);
    ...
    mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
    // add start
    mButtonDispatchers.put(R.id.screenshot, new ButtonDispatcher(R.id.screenshot));
    mButtonDispatchers.put(R.id.nav_power, new ButtonDispatcher(R.id.nav_power));
    // end 
    ...
}


// add start
public ButtonDispatcher getScreenshotButton() {
   return mButtonDispatchers.get(R.id.screenshot);
}

public ButtonDispatcher getNavPowerButton() {
   return mButtonDispatchers.get(R.id.nav_power);
}
// end

...

private void updateIcons(Configuration oldConfig) {
	...
	if (orientationChange || densityChange || dirChange) {
	    mBackIcon = getBackDrawable();
    }
	// add start
	mScreenshotIcon = getDrawable(R.drawable.ic_sysbar_screenshot_button);
	mNavPowerIcon = getDrawable(R.drawable.ic_sysbar_power_button);
	// end
}

...

public void updateNavButtonIcons() {
	...
	getHomeButton().setImageDrawable(homeIcon);
	getBackButton().setImageDrawable(backIcon);
	// add start
	getScreenshotButton().setImageDrawable(mScreenshotIcon);
	getNavPowerButton().setImageDrawable(mNavPowerIcon);
	// end
	...
}

1.5 设置监听事件

  • frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
import android.os.SystemClock; // add start

private static final long AUTODIM_TIMEOUT_MS = 2250;
// add start
private static final long SCREENSHOT_TIME_INTERVAL = 3000;
private long mLastClickScreenshotTime = 0;
// end

private void prepareNavigationBarView() {
     mNavigationBarView.reorient();
     ...
     // add start
     ButtonDispatcher screenshotButton = mNavigationBarView.getScreenshotButton();
     screenshotButton.setOnClickListener(this:: screenshotClick);
     screenshotButton.setVisibility(View.VISIBLE);
     
     ButtonDispatcher navPowerButton = mNavigationBarView.getNavPowerButton();
     navPowerButton.setOnClickListener(this:: navPowerClick);
     navPowerButton.setVisibility(View.VISIBLE);
     // end
}

...

// add start
private void navPowerClick(View v) {
     Intent intent=new Intent("android.intent.action.NAV_POWER");
     getContext().sendBroadcast(intent);
}

private void screenshotClick(View v) {
    long nowTime = SystemClock.elapsedRealtime();
    if (nowTime - mLastClickScreenshotTime < SCREENSHOT_TIME_INTERVAL) {
        return;
    }
    Intent intent=new Intent("android.intent.action.SCREENSHOT");
    getContext().sendBroadcast(intent);
    mLastClickScreenshotTime = nowTime;
}
// end

1.6 截屏和电源键功能实现

  • frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
 @Override
 public void init(Context context, IWindowManager windowManager,
     WindowManagerFuncs windowManagerFuncs) {
     ...
     // add start
     // register for nav_power click broadcasts
     filter=new IntentFilter();
     filter.addAction("android.intent.action.NAV_POWER");
     context.registerReceiver(mNavPowerReceiver, filter);
     
     // register for screenshot broadcasts
     filter=new IntentFilter();
     filter.addAction("android.intent.action.SCREENSHOT");
     context.registerReceiver(mScreenshotReceiver, filter);
     // end
     ...
}

// add start
BroadcastReceiver mScreenshotReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        mHandler.post(mScreenshotRunnable);
    }
};

BroadcastReceiver mNavPowerReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        showGlobalActionsInternal();
    }
};
// end

底下的patch中有Settings中添加延时截屏和控制图标显示开关的修改
传送门

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

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

相关文章

远程桌面-出现身份验证错误

1. 打开本地组策略编辑器&#xff0c;可以按winr组合键输入gpedit.msc命令打开。 2. 选择“计算机配置”--“管理模板”--“系统”--“凭据分配”&#xff0c;在“凭据分配”设置中选择“加密数据库修正”。 3. 在“加密数据库修正”对话框中选择“已启动”&#xff0c;保护级别…

Redis解决Session共享问题

文章目录 一、集群Session共享问题二、Redis存储验证码和对象三、解决状态登录刷新问题 一、集群Session共享问题 session共享问题&#xff1a;多台Tomcat并不共享session存储空间&#xff0c;当请求切换到不同tomcat服务器时导致数据丢失的问题 tomcat可以进行多台tomcat进行…

主数据管理:识别主数据

1.识别主数据的两个方法 1.1主数据特征识别法 主要评估企业全部数据中的各类主数据是否符合主数据的每个特征&#xff0c;如发现任何不符合主数据特征的数据&#xff0c;则将其剔除出主数据管理的范畴。 高价值性&#xff1a;主数据具备极高的业务价值。主数据描述企业最核心的…

全面了解JavaScirpt 的垃圾(garbage collection)回收机制

全面了解JavaScirpt 的垃圾(garbage collection)回收机制 一、垃圾回收机制—GC javascript具有自动垃圾回收机制(GC:Garbage Collecation)&#xff0c;也就是说&#xff0c;执行环境会负责管理代码执行过程中使用的内存。 原理&#xff1a;垃圾收集器会定期&#xff08;周期性…

超宽带(UWB)无线通信的技术特点

近年来&#xff0c;超宽带(UWB)无线通信成为短距离、高速无线网络最热门的物理层技术之一。 UWB的产生与发展 超宽带(UWB)有着悠久的发展历史&#xff0c;但在1989年之前&#xff0c;超宽带这一术语并不常用&#xff0c;在信号的带宽和频谱结构方面也没有明确的规定。1989年&am…

Django_haystack全文搜索

haystack是全文搜索的框架&#xff0c;支持whoosh、solr、Xapian、Elasticsearc四种全文检索引擎&#xff0c;点击查看官方网站。 whoosh是用纯Python编写的全文搜索引擎&#xff0c;虽然性能比不上sphinx、xapian、Elasticsearc等&#xff0c;但是无二进制包&#xff0c;程序…

C语言为什么是世界上最难的语言?看完你就明白了

在当前的信息技术领域&#xff0c;C语言在许多大型科技公司中扮演着重要角色&#xff0c;如谷歌、苹果和微软。这些公司不仅开发软件&#xff0c;还专门设计硬件&#xff0c;例如AMD、英传达和英特尔等公司。它们都使用C加速库来提高软件性能。 C语言之所以难以掌握&#xff0…

一个简单不报错的summernote 图片上传案例

一个简单不报错的summernote 图片上传案例 一个比较完整的summernote上传图片的案例&#xff0c;没有后台&#xff08;上传图片网上案例太多&#xff09;&#xff0c;只有前端js.修正了网上提供的&#xff0c;但是有bug的代码。 这个例子&#xff0c;js保证不报错。亲测可用 …

windows mysql服务自动启动 错误模块名称:ntdll.dll

在windows11家庭版系统安装mysql后&#xff0c;偶尔有mysql服务自动启动失败的问题&#xff0c;大体的原因就是MySQL的启动服务不能在Windows规定的启动时间内完成准备&#xff0c;于是就会停止其启动程序。windows事件日志如下&#xff1a; 方法一 &#xff1a; 检查确定文件…

计算机网络完结篇(从键入网址到响应页面-->HTTP常见面试题-->TCP三次握手及挥手-->TCP超时重传等特性-->Ip地址)

1. 基础篇 从键入网址到响应页面 1. 解析URL 生成HTTP请求信息 解析URL之后&#xff0c;浏览器确定了Web服务器和文件名&#xff0c;然后就是根据信息来生成HTTP请求信息。 2. 真实地址查询 DNS DNS服务器&#xff1a; 在第一步解析URL获取到对应的HTTP请求信息之后&#xf…

React 之 CSS编写方式

一、概述 整个前端已经是组件化的天下&#xff0c;而CSS的设计就不是为组件化而生的&#xff0c;所以在目前组件化的框架中都在需要一种合适的CSS解决方案 在组件化中选择合适的CSS解决方案应该符合以下条件&#xff1a; 可以编写局部css&#xff1a;css具备自己的具备作用域&a…

实现一个vscode插件:打开多个vscode项目时根据.nvmrc文件自动切换nvm

开发背景与最终功能 需要维护一些老项目&#xff0c;同时开发新项目时&#xff0c;切换nvm很烦人 最终实现vscode插件&#xff1a;每个vscode实例打开一个项目&#xff0c;切换vscode实例时能自动切换版本&#xff08;需要项目根目录有一个.nvmrc文件&#xff09; 插件下载 …

nextjs13中cssModule设置子标签的样式

前言 最近在学习nextjs中发现&#xff0c;如果在cssModule文件中直接设置子标签的样式比较麻烦&#xff0c;最后在网上看到一种方式可以解决&#xff0c;方式如下。 ps: 此方式不一定最优&#xff0c;因为在我看来此代码耦合性太高了&#xff0c;看着不太舒适&#xff0c;因为…

保姆级指南|APP原型设计怎么做?手把手教学超详细!

在数字化产品研发过程中&#xff0c;原型设计扮演着至关重要的角色。不夸张的说&#xff0c;产品原型很大程度决定了最终产品的成功与否。随着主流产品载体的更迭和发展&#xff0c;原型设计也在不断的演进。也产生了网页原型设计&#xff0c;桌面端app原型设计&#xff0c;移动…

PyTorch模型创建与nn.Module

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/dive-into-AI 】或者公众号【AIShareLab】回复 pytorch教程 也可获取。 文章目录 模型创建与nn.Modulenn.Module 总结 模型创建与nn.Module 创建网络模型通常有2个要素&#xff1a; 构建子模块拼接…

Redis 优惠卷秒杀(二) 异步秒杀、基于Stream的消息队列处理

目录 基于Stream的消息队列 Redis优化秒杀 登录头 改进秒杀业务&#xff0c;调高并发性能 Redis消息队列实现异步秒杀 ​编辑基于List结构模拟消息队列 基于PuSub的消息队列 ​编辑 基于Stream的消息队列 Redis消息队列 基于Stream的消息队列 Redis优化秒杀 登录头 改…

skywalking安装

目录 skywalking部署示意图 server安装 裸机安装 docker单节点安装 docker集群安装 k8s安装 helm安装(官方) k8s yaml安装 动态配置安装 client agent安装 skywalking部署示意图 skywalking ui - web界面管理程序oap server - skywalking服务程序nacos - skywalking集…

数字孪生水务系统可视化管理平台有效缓解城市供水压力

针对传统自来水厂供水水质安全隐患大&#xff0c;运行管理落后等问题&#xff0c;基于数字孪生技术构建全厂三维立体模型,在电脑前就可以掌握全厂管线、设备运行情况,遇到预案中的突发事件还可以给出辅助决策方案。从根本上有效提高水厂运行管理效率,增强对水质变化的应对能力,…

分析shein独立站成功的原因

近年来&#xff0c;Shein独立站在快时尚领域声名鹊起&#xff0c;成为许多时尚消费者的首选网站。面对激烈的竞争&#xff0c;它依然能够站稳脚跟并不断壮大。那么&#xff0c;Shein独立站成功的原因是什么呢&#xff1f; Shein独立站——以消费者为中心的运营模式 Shein独立站…

【Python】Locust持续优化:InfluxDB与Grafana实现数据持久化与可视化分析

在进行性能测试时&#xff0c;我们需要对测试结果进行监控和分析&#xff0c;以便于及时发现问题并进行优化。 Locust在内存中维护了一个时间序列数据结构&#xff0c;用于存储每个事件的统计信息。 这个数据结构允许我们在Charts标签页中查看不同时间点的性能指标&#xff0c…