SystemUi状态栏主要控件

本文详细介绍了Android系统中运营商信息、时间日期、系统图标、电池及通知图标等关键控件的工作原理和显示逻辑。运营商信息由CarrierText和OperatorNameView控件管理,时间日期由Clock和DateView控制,系统图标包括WiFi、信号和其它图标,电池控件BatteryMeterView实现电量显示和动画效果,通知图标同样基于StatusBarIconView。所有图标控件的显示更新都涉及特定的Controller和Callback机制,通过监听状态变化来刷新显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.运营商信息控件

运营商的控件有两个,一个是锁屏下显示的CarrierText,一个是解锁下显示的OperatorNameView。解锁状态下的OperatorNameView默认显示为空,只有当插入sim卡,并检测到sim卡状态已经准备好后才会显示运营商信息,具体控制是由KeyguardupdateMonitorCallback监听sim状态变化执行updateText方法进行更新信息;锁屏下的运营商信息显示由CarrierTextController控制,通过KeyguardUpdateMonitor -Callback的onSimStateChanged方法监听sim卡状态变化,onRefreshCarrierInfo实时刷新sim卡状态信息,通过updateCarrierText方法获取sim卡状态信息,之后封装显示信息,调用CarrierTextCallback的方法updateCarruerInfo,而在CarrierText中实现了这个方法,并实现更新显示信息。

CarrierText:监听 CarrierTextController,封装了 KeyguardUpdateMonitorCallback 接口。

路径为frameworks/base/packages/SystemUI/src/com/android/keyguard/CarrierText.java。

 OperatorNameView:实现了 KeyguardUpdateMonitorCallback 接口,用于监听 sim 卡信息的变化并更 新运营商信息。路径为:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java。

这两个控件的区别在于,CarrierText 显示所有状态下的运营商信息,而 OperatorNameView 只显示能正常时的运营商信息。

二.时间和日期控件

时钟日期的显示默认是使用网络提供的时间和时区,也可以自定义,其中时间的格式有24小时制和12小时制,这里的设置在TimerFormatPreferenceController中设置Settings.System数据库中添加了 “TIME_12_24”信息,值是null或者24,之后在显示控制类中获取这个值来显示。在DateFormat类的is24HourFormat()方法进行了处理和判断。

时间和日期分别由两个不同的控件控制:

Clock:时间控件,路径为 /frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java

DateView:日期控件,路径为 /frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java

DataView 的日期格式不受 Settings 中的日期格式控制,如需修改可以在 quick_qs_status_icons.xml 中的 com.android.systemui.statusbar.policy.DateView 内添加 systemui:datePattern 属性,然后自定义时间格式。

三.系统图标控件

Android 11.0 延续了 Android 9.0 中的系统图标设计,系统中包含的图标如图所示。

frameworks/base/core/res/res/values/config.xml中的config_statusBarIcons里。

这些图标都定义在了/frameworks/base/core/res/res/values/config.xml 中的 config_statusBarIcons 里,如图所示:

图标控件

Android 11.0 版本里的系统图标控件分为三种:

l StatusBarWifiViewwifi 图标

l StatusBarMoblieview:信号图标

l StatusBarIconView:其他图标,如蓝牙、热点、闹钟等

系统图标关系如图所示。

系统图标的显示过程不同于其他的状态栏图标,系统图标只有在某些功能发现变化时才会显示或更新。系统图标的更新控制基本都集中在StatusBarSignalPolicy.java和PhoneStatusBarPolicy.java里, 其分别控制的系统图标如下图所示,可以看到StatusBarSignalPolicy主要控制信号类系统图标,PhoneStatusBarPolicy主要控制状态类系统图标。

系统图标的显示流程大体类似,只是功能控制类不同。大体都是通过各自的Controller类监听功能状态,然后通过CallBack接口调Policy类,再通过IconController来刷新图标,如下图是 大致更新过程。

图标的显示更新都是由相应的控制类监听触发notifyListener方法,之后通过callback触发policy,再通过StatusBarIconController显示刷新小图标,这里设置图标的大小是通过读取status_bar_icon_size的值,这里为22dip。

图标显示由图标容器StatusIconContainer控制,在这个类中绘制图标的显示逻辑,其中方法calculateIconTranslations()计算图标的具体显示逻辑。

四.电池控件 

 电池控件是frameworks\base\packages\SystemUI\src\com\android\systemui\BatteryMeterView.java。此控件平台有做客制化,主要是实现充电动画功能,此功能通过config_battery_animation属性来控制。另一个需要关注的是电池百分比显示功能,此功能有两种方式实现,一种是调用setForceShowPercent()方法,来强制显示百分比,这就是锁屏状态栏显示百分比使用的方式;另一种是设置Setting.System数据库里的SHOW_BATTERY_PERCENT值来控制,这个是Settings设置显示电池百分比的方式。

电量显示有两种模式,一种是单纯显示电量图标,一种是显示图标加电量百分比,且充电模式下,会有充电动画,由ThemedBatteryDrawable的setCharging方法控制,电量的视图由自定义view-BatteryMeterView完成,电池有保护模式,充电模式下,电量处于40%至60%时,不再进行充电,所以会关闭充电动画,可以通过设置应用设置的全局节点信息battery_protected判断,电量切换显示百分比在设置应用也设置Settings.System数据库,key为SHOW_BATTERY_PERCENT,通过key在电量视图控制类进行处理。

电池图标的绘制都是代码画出来的,在自定义view加载了ThemedBatteryDrawable类型的drawable,就是使用这个绘制图标的,里面loadPaths()方法就是去加载电池图标资源的路径。

路径在frameworks/base/core/core/res/res/values/config.xml中

config_batterymeterPerimeterPath 电池外框,空心的

config_batterymeterErrorPerimeterPath 电池外框,空心的,这个用来画battery saver模式的外框,路径一样只是颜色不一样

config_batterymeterFillMask 电池内框,就是电量

config_batterymeterBoltPath 闪电,充电的

config_batterymeterPowersavePath 加号

可以将这些资源路径放在vector中查看图标具体长什么样子,之后自己客制化,之后在通过draw()方法进行绘制图标。

 五.通知图标控件

通知图标控件其实也是StatusBarIconView,通知图标的创建和更新流程大致如下图

六.图标容器控件

Android 11.0 中有两个容器控件:

l StatusIconContainer:系统图标容器控件,是系统图标的父类控件。

l NotificationIconContainer:通知图标容器控件,是通知图标的父类控件。

用户根据当前容器控件的大小来控制子控件的显示状态:

l STATE_ICON0

l STATE_HIDDEN1

l STATE_DOT2

0 代表显示图标,1 代表图标隐藏,2 代表图标隐藏显示圆点。

StatusIconContainer 控制子控件显示状态的核心方法是 calculateIconTranslations,详细操作步骤如下。

NotificationIconContainer 显示逻辑与之基本类似。

步骤 1 按从后到前的顺序计算当前需要显示的图标数,并计算剩余的空间 transaltionx

步骤 2 通过 state.xTranslation 计算第一个无法显示的图标 index

步骤 3 通过 firstUnderflowIndex 将第一个无法显示的图标设置为 STATE_ICON

1)控件宽度    2)除去paddingEnd宽度

3)按从后到前的顺序计算当前需要显示的图标数,并计算剩余的空间translationX 

通过state.xTranslation计算出第一个无法完整显示的图标index

 通过firstUnderflowIndex将第一个无法完整显示的图标设置成STATE_DOT,并将前面的图标设置成STATE_HIDDEN

### Android SystemUI 横屏状态下状态栏自定义或适配解决方案 在 Android 中,`SystemUI` 是负责显示设备上各种 UI 组件的核心模块之一,其中包括通知栏、快速设置面板以及状态栏等。当涉及到横屏模式下状态栏的定制或者适配时,开发者通常需要深入理解 `SystemUI` 的源码结构并进行相应的修改。 #### 1. **分析现状** Android 设备的状态栏默认设计是为了适应竖屏布局,在切换到横屏模式时可能会遇到一些视觉上的不一致问题。这可能包括图标排列不当、文字方向错误或其他界面错位现象[^1]。因此,针对这些问题,可以通过以下方式来实现横屏模式下的状态栏自定义或适配: --- #### 2. **通过 XML 资源文件调整** 对于简单的样式更改,可以利用资源限定符机制创建特定于横屏模式的布局文件。例如,可以在 `res/layout-land/` 文件夹中放置专门用于横屏的布局文件。这些文件会自动覆盖默认的竖屏布局配置[^2]。 ```xml <!-- res/layout-land/status_bar.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- 定义适合横屏展示的内容 --> </LinearLayout> ``` 上述方法适用于不需要大幅改动现有逻辑的情况,仅需微调视图即可满足需求。 --- #### 3. **重写 Status Bar 类** 如果需要更深层次的功能扩展,则可以直接继承或修改 `StatusBarView` 及其子类的行为。具体操作如下: - 找到 `com.android.systemui.statusbar.phone.StatusBar` 这一核心类。 - 修改其中关于屏幕旋转事件处理的部分代码,确保在不同方向下都能正确渲染组件位置与大小[^3]。 以下是简化版伪代码示例: ```java // 假设我们正在修改 StatusBar.java @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { adjustForLandscapeMode(); // 自定义横屏行为 } else { resetToPortraitMode(); // 复原至竖屏状态 } } private void adjustForLandscapeMode() { // 设置新的宽高比例或者其他属性 } ``` 此部分涉及较多底层细节,建议熟悉整个项目架构后再尝试实施。 --- #### 4. **动态更新 UI 元素** 除了静态资源配置外,还可以借助 Java/Kotlin 动态计算各控件尺寸,并实时应用变化后的参数值给目标 View 对象。比如监听传感器数据获取当前角度信息后即时刷新页面呈现效果[^4]。 下面是一个基于 OrientationListener 实现的例子: ```java OrientationEventListener orientationListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_UI) { @Override public void onOrientationChanged(int orientation) { if ((orientation >= 0 && orientation < 45) || (orientation > 315)) { updateUiForPortrait(); } else if (orientation >= 135 && orientation <= 225){ updateUiForReverseLandscape(); } else if (orientation > 45 && orientation < 135){ updateUiForLandscape(); } /* ... */ } }; ``` 记得适时释放 listener 防止内存泄漏等问题发生! --- #### 5. **注意事项与其他技巧** - 测试过程中务必考虑多分辨率支持情况; - 如果计划发布第三方 ROM 应用程序,请遵循开源协议规定; - 使用 AOSP 提供的标准 API 接口而非硬编码数值以增强兼容性[^5]; --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值