SystemUI下拉框新增音量控制条

Android产品下拉框一直只有亮度条没有音量控制条。 为了方便控制音量,普遍都是底部导航栏添加音量加减按钮,在Android10以后,大家普遍用上了手势导航,去掉底部导航栏。 目前需要再下拉框中可以直接控制音量。

文章目录

  • 前言
  • 需求及效果
  • 基础必备
    • 修改文件:
  • 修改说明
    • 去掉长按亮度条不隐藏QSPanel
    • 新增音量进度条到QS面板,放到亮度进度条下方
      • 几个相关类引入
      • 简要对部分类的简单分析
        • BrightnessSlider
        • BrightnessSlider
        • QSPanelController
          • 创建mBrightnessSlider 变量的创建:
          • setBrightnessView
  • 实现方案
    • 布局
    • 构造控制器并绑定View
    • 业务
      • StatusBar
      • StatusBarPhoneModule
      • QSPanel QSPanelController
      • 其它相关类
  • 资源


前言

在Android12平台,QS 面板上,亮度控制条下面添加音量条,方便控制音量。

需求及效果

Android12 版本

  1. RK和MTK平台在下拉框QS面板中,亮度条的下方新增音量条控制器 亮度条长按不隐藏QS面板
  2. 亮度条长按不隐藏QS面板

在这里插入图片描述

在这里插入图片描述

基础必备

SystemUI 相关知识,务必做到基本流程了解、概念、架构、布局,方便实现基础功能和理解业务修改。
参考资料:截屏功能添加中的SystemUI基础描述

#修改说明
详细说明如下,参考修改文件和新增文件即可完成功能,实现需求

修改文件:

vendor/mediatek/proprietary/packages/apps/SystemUI/AndroidManifest.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/classifier/Classifier.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/qs/QSAnimator.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/qs/QSPanel.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/qs/QSPanelController.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java`## 新增文件:```java
vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable-hdpi/icon_volume_test.png
vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable-mdpi/icon_volume_test.png
vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable-xhdpi/icon_volume_test.png
vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable-xxhdpi/icon_volume_test.png
vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable-xxxhdpi/icon_volume_test.png
vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/ic_volume.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/volume_progress_drawable.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/volume_progress_full_drawable.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/res/layout/quick_settings_volume_dialog.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/settings/volume/
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/util/ApplicationContextProvider.kt
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/util/ContextProvider.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/util/SoundUtils.kt

修改说明

修改说明详细文档,方便理解

去掉长按亮度条不隐藏QSPanel

  com.android.systemui.statusbar.policy.BrightnessMirrorController  亮度条镜控制器com.android.systemui.settings.brightness.BrightnessSliderSeekBar.OnSeekBarChangeListener回调方法中屏蔽mirrorController 的相关回调控制具体代码如下:private final SeekBar.OnSeekBarChangeListener mSeekListener =new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {if (mListener != null) {mListener.onChanged(mTracking, progress, false);}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {mTracking = true;if (mListener != null) {mListener.onChanged(mTracking, getValue(), false);}/*if (mMirrorController != null) {mMirrorController.showMirror();mMirrorController.setLocationAndSize(mView);}*/}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {mTracking = false;if (mListener != null) {mListener.onChanged(mTracking, getValue(), true);}/*if (mMirrorController != null) {mMirrorController.hideMirror();}*/}};

新增音量进度条到QS面板,放到亮度进度条下方

实现方案,参考源码中亮度条实现的方式实现

几个相关类引入

com.android.systemui.settings.brightness 包下

     BrightnessController.java   :对外的控制器 BrightnessController implements ToggleSlider.Listener   BrightnessSlider.java       : 本质上也是一个View,带了ViewController控制器,extends    ViewController<BrightnessSliderView> implements ToggleSliderToggleSlider.java           : 定义进度条控制器的接口,如:进度条变化回调 onChanged、setMax、getMax、getValue、setValueBrightnessDialog.java       :显示音量的Activity,里面加载的是Dialog,源码暂未使用  BrightnessSliderView.java   :SeekBar的根布局文件,包裹ToggleSeekBarView,本质是一个FrameLayout 布局ToggleSeekBar.java          :SeekBar 

简要对部分类的简单分析

BrightnessSlider

中的Factory类,来构造BrightnessSlider, 这里面加载了布局 quick_settings_brightness_dialog,
在上面已经描述 这个BrightnessSlider 本质就是一个带控制器ViewController的view

 public static class Factory {private final FalsingManager mFalsingManager;@Injectpublic Factory(FalsingManager falsingManager) {mFalsingManager = falsingManager;}/*** Creates the view hierarchy and controller** @param context a {@link Context} to inflate the hierarchy* @param viewRoot the {@link ViewGroup} that will contain the hierarchy. The inflated*                 hierarchy will not be attached*/public BrightnessSlider create(Context context, @Nullable ViewGroup viewRoot) {int layout = getLayout();BrightnessSliderView root = (BrightnessSliderView) LayoutInflater.from(context).inflate(layout, viewRoot, false);return new BrightnessSlider(root, mFalsingManager);}/** Get the layout to inflate based on what slider to use */private int getLayout() {return R.layout.quick_settings_brightness_dialog;}}
BrightnessSlider
 类的Factory类,来构造BrightnessController
/** Factory for creating a {@link BrightnessController}. */public static class Factory {private final Context mContext;private final BroadcastDispatcher mBroadcastDispatcher;@Injectpublic Factory(Context context, BroadcastDispatcher broadcastDispatcher) {mContext = context;mBroadcastDispatcher = broadcastDispatcher;}/** Create a {@link BrightnessController} */public BrightnessController create(ToggleSlider toggleSlider) {return new BrightnessController(mContext, toggleSlider, mBroadcastDispatcher);}}

重点关注构造方法中传递了一个ToggleSlider参数,如果传递ToggleSlider 实现类,那么就实现了控制器和view 的绑定。
控制器中可以通过传递过来的view 来控制view 的各种状态和设置内容。 追踪一下这块创建和添加view 地方:
BrightnessController-> createcreate(ToggleSlider toggleSlider)

QSPanelController

调用地方:QSPanelController 构造方法中:*

        mBrightnessSliderFactory = brightnessSliderFactory;//通过factory里的create方法生成mBrightnessSlider = mBrightnessSliderFactory.create(getContext(), mView);//mView就是上边的QSPanel,可以看到,亮度条是动态添加到容器里的mView.setBrightnessView(mBrightnessSlider.getRootView());//通过factory里的create方法生成mBrightnessController = brightnessControllerFactory.create(mBrightnessSlider);
创建mBrightnessSlider 变量的创建:
mBrightnessSlider = mBrightnessSliderFactory.create(getContext(), mView);-> BrightnessSlider 的create 方法/*** Creates the view hierarchy and controller** @param context a {@link Context} to inflate the hierarchy* @param viewRoot the {@link ViewGroup} that will contain the hierarchy. The inflated*                 hierarchy will not be attached*/public BrightnessSlider create(Context context, @Nullable ViewGroup viewRoot) {int layout = getLayout();BrightnessSliderView root = (BrightnessSliderView) LayoutInflater.from(context).inflate(layout, viewRoot, false);return new BrightnessSlider(root, mFalsingManager);}

return 返回的不就是创建的它的视线的子类吗?BrightnessSliderView
这样就间接实现了 对外Brightness 控制器BrightnessController 和 view 对应BrightnessSliderView 的绑定。

setBrightnessView
关注另外一个点:mView.setBrightnessView(mBrightnessSlider.getRootView());QSPanelController 里面的mView 肯定是QSPanel, setBrightnessView 又是做什么的呢? 且看代码/*** Add brightness view above the tile layout.** Used to add the brightness slider after construction.*/public void setBrightnessView(@NonNull View view) {if (mBrightnessView != null) {removeView(mBrightnessView);mMovableContentStartIndex--;}addView(view, 0);mBrightnessView = view;setBrightnessViewMargin();mMovableContentStartIndex++;}

就是在QS面板里面添加View,这个地方就是QS 、QQS 相关的核心思想,根布局下面的子布局,都是通过add 添加进去的。

实现方案

实现方案和思想,完全参考亮度进度条的实现方案,故必须对SystemUI有所了解,且对亮度条控制亮度流程、思想比较熟悉,照抄照搬!
几个类的定义,实现volume 控制条,创建几个volume 调节相关的类,

    com/android/systemui/settings/volume/	  VolumeController.java VolumeSlider.javaVolumeSliderView.java和对应的布局文件quick_settings_volume_dialog

布局

quick_settings_volume_dialog 完整版本如下:其中SeekBar 完全延用brightness中的ToggleSeekBar
 <com.android.systemui.settings.volume.VolumeSliderViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/brightness_slider"android:layout_width="match_parent"android:layout_height="@dimen/brightness_mirror_height"android:layout_gravity="center"android:contentDescription="@string/accessibility_brightness"android:importantForAccessibility="no" ><com.android.systemui.settings.brightness.ToggleSeekBarandroid:id="@+id/slider"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:minHeight="48dp"android:thumb="@null"android:background="@null"android:paddingStart="0dp"android:paddingEnd="0dp"android:progressDrawable="@drawable/volume_progress_drawable"android:splitTrack="false"/></com.android.systemui.settings.volume.VolumeSliderView>

构造控制器并绑定View

        QSPanelController 类中,构建View并构建管理view控制器 Control,同时绑定ViewmVolumeSliderFactory = volumeSliderFactory;mVolumeSlider = mVolumeSliderFactory.create(getContext(), mView);mView.setVolumeView(mVolumeSlider.getRootView());mVolumeController = volumeControllerFactory.create(mVolumeSlider);

业务

StatusBar

构造方法中,构建 VolumeSlider.Factory mVolumeSliderFactory,通过注解构造方法实现,其实就是加载View,布局就加载出来了

StatusBarPhoneModule

StatusBarPhoneModule.java 中,生成的StatusBar的, 也是在这里,加载传递VolumeSlider 给StatusBar 的,具体实现方式完全通过Dragger注解来实现。

  /*** Provides our instance of StatusBar which is considered optional.*/@Provides@SysUISingletonstatic StatusBar provideStatusBar(....VolumeSlider.Factory volumeSliderFactory,....){return new StatusBar(...volumeSliderFactory,...);};

QSPanel QSPanelController

QSPanel QSPanelController 去掉相关的BrightnessMirrorController[镜像控制条,需求一种已经去掉这个类 或者 暂时无用就屏蔽掉]
同时分析,亮度条和进度条是怎么添加到了QSPanel 中去的

  • QSPanel 中添加brightnessSeekView 和 volumSeekView 并设置margin
 public void setVolumeView(@NonNull View view) {Log.d(TAG,"setVolumeView");if (mVolumeView != null) {removeView(mVolumeView);mMovableContentStartIndex--;}addView(view, 1);mVolumeView = view;setVolumeViewMargin();mMovableContentStartIndex++;//view.setVisibility(TunerService.parseIntegerSwitch(newValue, true) ? VISIBLE : GONE);}private void setVolumeViewMargin() {if (mVolumeView != null) {MarginLayoutParams lp = (MarginLayoutParams) mVolumeView.getLayoutParams();lp.topMargin = mContext.getResources().getDimensionPixelSize(R.dimen.qs_brightness_margin_top);lp.bottomMargin = mContext.getResources().getDimensionPixelSize(R.dimen.qs_brightness_margin_bottom);mVolumeView.setLayoutParams(lp);}}
  • QSPanelController
    QSPanelController 类中,构建View并构建管理view控制器 Control
        mVolumeSliderFactory = volumeSliderFactory;mVolumeSlider = mVolumeSliderFactory.create(getContext(), mView);mView.setVolumeView(mVolumeSlider.getRootView());mVolumeController = volumeControllerFactory.create(mVolumeSlider);  

其它相关类

    com.android.systemui.util  目录下几个类:SoundUtils.kt                   :自定义音量控制工具,将15级别音量调整为100级别,方便展示更加细腻化 ContextProvider.java  ApplicationContextProvider.kt           :和ApplicationContextProvider 一起,提供全局的Context支持,在AndroidManifest.xml中配置    
 <!-- Add a Provider to get Application in Project. --><providerandroid:name="com.android.systemui.util.ApplicationContextProvider"android:authorities="com.android.systemui.contextprovider"android:exported="false"android:grantUriPermissions="true"></provider>	

资源

RK Android12 SystemUI SystemUI源码方便调试
资源实现源码待RK平台集成后,晚些释放。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day33

一、linux系统中的库 库在linux系统中是一个二进制文件&#xff0c;它是由XXX.c&#xff08;不包含main函数&#xff09;文件编译而来的&#xff0c;分为静态库和动态库。 库在系统中的内容是不可见的&#xff0c;是一个二进制乱码 当程序需要使用库中的相关函数时&#xff0c;…

安装docker 遇到异常Could not resolve host: mirrorlist.centos.org; 未知的错误

问题 安装docker 遇到异常 Could not retrieve mirrorlist http://mirrorlist.centos.org/?release7&archx86_64&repoos&infrastock error was 14: curl#6 - “Could not resolve host: mirrorlist.centos.org; 未知的错误” 1、安装Docker依赖包 yum install …

基于SpringBoot的论坛系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图详细视频演示技术栈系统测试为什么选择我官方认证玩家&#xff0c;服务很多代码文档&#xff0c;百分百好评&#xff0c;战绩可查&#xff01;&#xff01;入职于互联网大厂&#xff0c;可以交流&#xff0c;共同进步。有保障的售后 代码参考数据库参…

Android 12系统源码_多屏幕(二)模拟辅助设备功能开关实现原理

前言 上一篇我们通过为Android系统开启模拟辅助设备功能开关&#xff0c;最终实现了将一个Activity显示到多个屏幕的效果。 本篇文章我们具体来分析一下当我们开启模拟辅助设备功能开关的时候&#xff0c;Android系统做了什么哪些操作。 一、模拟辅助设备功能开关应用位置 …

存储实验:华为异构存储在线接管与在线数据迁移(Smart Virtualization Smart Migration 特性)

目录 目的实验环境实验步骤参考文档1. 主机安装存储多路径2. v2存储创建Lun&#xff0c;映射给主机&#xff1b;主机分区格式化&#xff0c;写数据3. 将v2存储映射该成映射到v3存储上(v3存储和v2之间链路搭建&#xff0c;测通&#xff0c;远端设备&#xff09;&#xff08;Smar…

便利店(超市)管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图详细视频演示技术栈系统测试为什么选择我官方认证玩家&#xff0c;服务很多代码文档&#xff0c;百分百好评&#xff0c;战绩可查&#xff01;&#xff01;入职于互联网大厂&#xff0c;可以交流&#xff0c;共同进步。有保障的售后 代码参考数据库参…

中国:“虚拟资产”交易被列为公认的洗钱方式之一!最高法院承认加密货币交易!

2024年8月19日&#xff0c;最高人民法院和最高人民检察院表示&#xff0c;根据他们对反洗钱法的新解释&#xff0c;“虚拟资产”交易现已被列为公认的洗钱方式之一。这是中国首次针对此类资产类别采取此类举措&#xff0c;说明为应对加密货币和其他虚拟资产日益增长的使用&…

IO进程线程8.20

1.使用fgets获取文件的行号 #include <myhead.h> int main(int argc, const char *argv[]) {FILE *fp fopen("./1.txt","r");if(fpNULL){perror("fp");return -1;}char buf[30];int count 0;while(fgets(buf,sizeof(buf),fp)){count;}p…

为IntelliJ IDEA安装插件

安装插件 插件是开发工具的扩展程序&#xff0c;通常由第三方提供&#xff0c;当安装了插件后&#xff0c;原开发工作的菜单、按钮等开发环境可能会发生变化&#xff0c;例如出现了新的菜单项&#xff0c;或出现了新的按钮&#xff0c;甚至一些全新的编码方式&#xff0c;通常…

双向链表复习(C语言版)

目录 链表分类&#xff1a; 双向链表初始化&#xff1a; 双向链表的插入&#xff1a; 双向链表的打印&#xff1a; 双向链表的删除&#xff1a; 双向链表的指定结点位置查找&#xff1a; 双向链表的在指定位置之后插入数据&#xff1a; 注意&#xff1a;通过上文的指定…

地理科学专业| 中国大学排行榜(2024年)

地理科学专业| 中国大学排行榜&#xff08;2024年&#xff09;

客车制造5G智能工厂工业物联数字孪生平台,推进制造业数字化转型

制造业正经历着前所未有的变革&#xff0c;其中客车制造行业作为传统制造业的重要组成部分&#xff0c;正积极拥抱5G、工业物联网及数字孪生等先进技术&#xff0c;推动生产模式的全面升级与数字化转型。 客车制造5G智能工厂工业物联数字孪生平台的出现&#xff0c;不仅为行业…

【Linux】系列入门摘抄笔记-8-权限管理chmod/chown

Linux操作系统中文件的基本权限由9个字符组成&#xff0c;分别为属主、属组和其他用户&#xff0c;用于规定是否对文件有读、写和执行权限。 文件/目录的权限与归属 目录列表中&#xff0c;有9列 第一列&#xff1a;文件类型与权限&#xff08;共10个字符&#xff0c;分为四组…

电子木鱼+提肛+游戏地图,车机还能这么玩?

文/王俣祺 导语&#xff1a;电子木鱼、提肛训练、游戏级地图&#xff0c;你很难想象这些“直男关怀”是来自小鹏MONA M03的车机系统。最近&#xff0c;一批关于MONA M03车机功能的视频在网上疯传&#xff0c;一系列“没用但有趣”的功能广受年轻用户的好评&#xff0c;情绪价值…

linux上用anaconda创建一个新环境,并将nicegui的应用打包为一个可执行应用

先下载好anaconda linux版本 Download Anaconda Distribution | Anacondahttps://www.anaconda.com/download/之后运行 conda create --name py311 python3.11 --name py311 是环境名 python3.11 是python版本 安装完成后&#xff0c;运行 conda env list 得到 这时我们…

手机使用技巧:如何恢复Android手机不见的短信

在您的 Android 手机上丢失短信可能是一种令人沮丧的经历&#xff0c;尤其是在文本包含重要信息的情况下。幸运的是&#xff0c;有一些方法可以在Android上恢复已删除的短信。在这篇博文中&#xff0c;我们将讨论几种在Android手机上恢复已删除短信的方法。 为什么需要恢复Andr…

【python】逐步回归(多元线性回归模型中的应用)

文章目录 前言一、逐步回归1. 前进法&#xff08;Forward Selection&#xff09;2. 后退法&#xff08;Backward Elimination&#xff09;3. 逐步回归法&#xff08;Stepwise Regression&#xff09; 二、示例三、代码实现----python 前言 Matlab中逐步回归的实现可以使用 Mat…

软体水枪在灭火工作中发挥什么作用_鼎跃安全

火灾&#xff0c;这一频繁侵袭我们日常生活的灾难性事件&#xff0c;以其迅猛之势对人类的生存环境与日常生活构成了极其严重的破坏与威胁。它不仅能够在瞬间吞噬财产&#xff0c;更可怕的是&#xff0c;它无情地剥夺了生命&#xff0c;破坏了家庭&#xff0c;给社会留下了难以…

关于Ubuntu中使用命令行安装Qt的一些分享

以Ubuntu 22.04为例。 1、安装默认的Qt库 sudo apt-get install qtbase5-dev qtbase5-dev-tools qtchooser 这条指令执行完会出现 usr/lib/x86_64-linux-gnu/qt5 文件&#xff0c;并伴随5个子文件夹&#xff0c;结构如下&#xff1a; 并且会出现 usr/lib/qt5, usr/lib/x86_6…

第5节:Elasticsearch核心概念

我的后端学习笔记大纲 我的ElasticSearch学习大纲 1.Lucene和Elasticsearch的关系: 1.Lucene&#xff1a;最先进、功能最强大的搜索库&#xff0c;直接基于lucene开发&#xff0c;非常复杂&#xff0c;api复杂2.Elasticsearch&#xff1a;基于lucene&#xff0c;封装了许多luc…