Android7.0 SystemUI StatusBar和Notification代码浅析

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 程序入口 *
系统会启动SystemUIService
SystemUIService->onCreate

SystemUIApplication->startServicesIfNeeded()
创建所有SystemUI为base的类的对象
调用start()
如果bootCompleted调用onBootCompleted
比如 PhoneStatusBar的start和onBootCompleted

PhoneStatusBar -> BaseStatusBar -> SystemUI

继承于SystemUI的类如下:
extends SystemUI
PhoneStatusBar
KeyBoardUI
KeyguardViewMediator
RingtonePlayer
PowerUI
Recents
ShortcutKeyDispatcher
Divider
BaseStatusBar
SystemBars
TunerService
PipUI
StorageNotification
VolumeUI

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* view的创建过程 *

PhoneStatusBar
->createAndAddWindows创建statusbar的视图
->addStatusBarWindow 创建StatusbarWindow并追加到WindowManager作为系统的statusbar

StatusBarWindowView
PhoneStatusbar的成员mStatusBarWindow
其实就是super_status_bar.xml

PhoneStatusBarView extends PanelBar
mStatusBarView PhoneStatusBar的成员
对应status_bar.xml

NotificationPanelView
PhoneStatusBar的成员mNotificationPanel
StatusBarWindowView的成员mNotificationPanel
其实就是status_bar_expanded.xml

status_bar_expanded.xml
NotificationsQuickSettingsContainer
NotificationPanelView的成员mNotificationContainerParent
id = notification_container_parent,在status_bar_expanded.xml中

AutoReinflateContainer
NotificationPanelView的成员mQsAutoReinflateContainer
id = qs_auto_reinflate_container
构造函数中
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoReinflateContainer);
if (!a.hasValue(R.styleable.AutoReinflateContainer_android_layout)) {
throw new IllegalArgumentException(“AutoReinflateContainer must contain a layout”);
}
mLayout = a.getResourceId(R.styleable.AutoReinflateContainer_android_layout, 0);

实际是通过attrs中



去查找id为qs_auto_reinflate_container的layout文件中的android:layout属性对应的layout属性的值
android:layout=”@layout/qs_panel”

AutoReinflateContainer
inflateLayout();
会回调所有的Listener
一共有3个Listener
PhoneStatusbar中一个
NotificationPanelView中一个
NotificationQuickSettingsContainer中一个

mQsAutoReinflateContainer.addInflateListener(new InflateListener() {
@Override
public void onInflated(View v) {
mQsContainer = (QSContainer) v.findViewById(R.id.quick_settings_container);
mQsContainer.setPanelView(NotificationPanelView.this);
mQsContainer.getHeader().findViewById(R.id.expand_indicator)
.setOnClickListener(NotificationPanelView.this);

            // recompute internal state when qspanel height changes
            mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View v, int left, int top, int right, int bottom,
                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
                    final int height = bottom - top;
                    final int oldHeight = oldBottom - oldTop;
                    if (height != oldHeight) {
                        onQsHeightChanged();
                    }
                }
            });
            mNotificationStackScroller.setQsContainer(mQsContainer);
        }
    });

因此AutoReinflateContainer其实内部就是android:layout=”@layout/qs_panel”
也就是QSContainer,对应qs_panel.xml
qs_panel.xml包含4部分
quick_settings_panel ——>QSPanel quick setting打开状态
quick_status_bar_expanded_header ——>QuickStatusBarHeader quick setting收起的状态,包含编辑btn,setting btn,时间等,
最重要的是QuickQSPanel,代表quick setting收起状态
qs_detail ——>QSDetail quick setting中某一个setting相打开后的状态,
比如battery或者情景模式设定打开后的详情状态
包含两个btn,一个是more setting,一个是done
点击done返回QSPanel状态
点击more setting进入对应的设定页面

qs_customize ——>QSCustomizer quick setting detail编辑中的状态

quick_status_bar_expanded_header
QuickStatusBarHeader.java
其实是quick_status_bar_expanded_header.xml
这里面就包含了多个btn,切换用户,进入setting,下拉打开quick setting详细,编辑
里面包含
mHeaderQsPanel = (QuickQSPanel) findViewById(R.id.quick_qs_panel);
quick_qs_panel ——>QuickQSPanel

signal_cluster
status_bar.xml->system_icons.xml->signal_cluster_view.xml->signal_cluster
status_bar.xml是状态栏

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* QSPanel隐藏过程 *

NotificationPanelView status_bar_expanded.xml id=notification_panel
extends PanelView

PanelView ->mBar->PanelBar->panelExpansionChanged
NotificationPanelView PhoneStatusBarView

PhoneStatusBarView->animateCollapsePanels->
mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);

PanelBar的
panelExpansionChanged
通过PanelView的notifyBarPanelExpansionChanged调用的
这里使得最初显示了QuickQSPanel,隐藏了QSPanel

启动时通过BaseStatusBar->start()->createAndAddWindows()创建statusbar的view
之后通过disable
disable(switches[0], switches[6], false /* animate */);
调用PhoneStatusBar的
disable

12-07 15:38:45.695 1389-1389/com.android.systemui D/PhoneStatusBar: disable: < EXPAND* icons alerts system_info BACK* HOME* RECENT* clock SEARCH* quick_settings >
if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) {
animateCollapsePanels();
}
}

之后就会调用animateCollapsePanels();
animateCollapsePanels(flags, false /* force /, false / delayed */,
1.0f /* speedUpFactor */);
mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
mStatusBarView是PhoneStatusBarView,
PhoneStatusBarView extends PanelBar

collapsePanel在PanelBar中->PhoneStatusBarView
public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
true,false,1.0

panelView->NotificationPanelView
fling(0, false /* expand /, speedUpFactor, false / expandBecauseOfFalsing */);
fling(0, false, 1.0, false);

flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
flingToHeight(0, false, 0.0f, 1.0, false);

@Override
public void onAnimationEnd(Animator animation) {
if (clearAllExpandHack && !mCancelled) {
setExpandedHeightInternal(getMaxPanelHeight());
}
mHeightAnimator = null;
if (!mCancelled) {
notifyExpandingFinished();
}
notifyBarPanelExpansionChanged();
}

panelView->notifyBarPanelExpansionChanged();
mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f || mPeekPending
|| mPeekAnimator != null || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp()
|| mTracking || mHeightAnimator != null);

panelBar->panelExpansionChanged(float frac, boolean expanded) {
12-07 15:38:45.695 1389-1389/com.android.systemui V/PanelBar: panelExpansionChanged: start state=0, frac=0.0, expanded=false
12-07 15:38:45.695 1389-1389/com.android.systemui V/PanelBar: panelExpansionChanged: end state=0 [ fullyClosed ]
PanelView pv = mPanel;
pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);

public class NotificationPanelView extends PanelView
NotificationPanelView -> status_bar_expanded.xml里面包含QSPanel
这里就将QSPanel隐藏掉了

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
清空所有Notification在
status_bar_notification_dismiss_all.xml中

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tiles每个tils对应一个quick setting icon
config.xml

wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night

QSTile.java
通过QSTileHost.createTile创建一个tile
TileQueryHelper.java构造函数->addSystemTiles创建所有Tile

构造函数是在QuickStatusBarHeader的onFinishInflate函数中调用的

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
quick_settings_panel ——>QSPanel
里面包含qs_paged_tile_layout ——>QSTileLayout
里面的每个item是QSTileView,包含icon和label,点击可以显示详情

QuickQSPanel
里面的每个item是QSTileBaseView,只有icon,点击不能显示详情

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Notification画面结构

NotificationContentView
ExpandableNotificationRow ——————————–一行可以扩展的Notification,包含NotificationChildrenContainer,
NotificationGuts,NotificationSettingsIconRow
在BaseStatusBar的inflateViews创建并赋值给Entry的row变量记录下来
NotificationChildrenContainer ——————————–包含NotificationHeaderView和Divider
NotificationHeaderView ——————————–包含Notification合并后的header,app icon,name,下拉btn
HybridNotificationView ——————————–ExpandableNotificationRow的两个成员变量mPrivateLayout和mPublicLayout对应的类
当多条收缩在一起的Notification中的一行收缩显示时使用这个View
NotificationGuts ——–notification_guts——-一条Notification的设定条目 包含icon title summary
设定相关radio btn,以及设定打开后的more setting和done btn
NotificationSettingsIconRow ——–notification_guts——-似乎是左右拖动Notification后显示出的Setting btn

HeadsUpEntry ——————————–从Android 5.0开始,如果notification priority设置为HIGH, MAX, 或者fullscreenIntent不为空,在非锁屏界面收到notification时屏幕上方会显示一个小悬浮窗口提醒用户,方便用户在不退出当前浏览界面的前提下快速响应该notification,即Heads-Up Notification(简称HUN)。

NotificationViewWrapper implements TransformableView
用于处理view动画,比如fadeIn fadeOut

BaseStatusBar的inflateViews
row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row,
parent, false);

ExpandableNotificationRow extends ActivatableNotificationView
ActivatableNotificationView extends ExpandableOutlineView
ExpandableOutlineView extends ExpandableView
ExpandableView extends FrameLayout
所以ExpandableNotificationRow根本上是个FrameLayout

Notification.Builder生成的Notification没有使用其他content layout,没有使用其他style的话
那么直接从Notification.Builder创建View

            cachedContentView = builder.createContentView();
            cachedBigContentView = builder.createBigContentView();
            cachedHeadsUpContentView = builder.createHeadsUpContentView();
            cachedPublicContentView = builder.makePublicContentView();

实际处理在Notification.java中
frameworks/base/core/java/android/app/Notification.java

主要用到的Layout文件
frameworks/base/core/res/res/layout/notification_template_material_base.xml
frameworks/base/core/res/res/layout/notification_template_right_icon.xml
frameworks/base/core/res/res/layout/notification_template_text.xml
frameworks/base/core/res/res/layout/notification_template_part_line1.xml
frameworks/base/core/res/res/layout/notification_template_header.xml
frameworks/base/core/res/res/layout/notification_template_material_big_base.xml

里面用到一些文字的style

frameworks/base/core/res/res/values/styles_material.xml

@color/white
@dimen/notification_text_size

<style name="TextAppearance.Material.Notification.Reply" />

<style name="TextAppearance.Material.Notification.Title">
    <item name="textColor">@color/white</item>
    <item name="textSize">@dimen/notification_title_text_size</item>
</style>

<style name="TextAppearance.Material.Notification.Line2">
    <item name="textSize">@dimen/notification_subtext_size</item>
</style>

<style name="TextAppearance.Material.Notification.Info">
    <item name="textColor">@color/white</item>
    <item name="textSize">@dimen/notification_subtext_size</item>
</style>

<style name="TextAppearance.Material.Notification.Time" parent="TextAppearance.Material.Notification.Info" />

<style name="TextAppearance.Material.Notification.Emphasis">
    <item name="textColor">#66000000</item>
</style>

<style name="Widget.Material.Notification.ProgressBar" parent="Widget.Material.Light.ProgressBar.Horizontal" />

<style name="Widget.Material.Notification.MessagingText" parent="Widget.Material.Light.TextView">
    <item name="layout_width">match_parent</item>
    <item name="layout_height">wrap_content</item>
    <item name="ellipsize">end</item>
    <item name="visibility">gone</item>
    <item name="textAppearance">@style/TextAppearance.Material.Notification</item>
</style>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Notification来源

BaseStatusBar.java
start时通过
mNotificationListener.registerAsSystemService(mContext,
new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
UserHandle.USER_ALL);
注册listener

private final NotificationListenerService mNotificationListener =
new NotificationListenerService() {
@Override
public void onNotificationPosted(final StatusBarNotification sbn,
final RankingMap rankingMap) {
来接收新的Notification

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
setSystemUiVisibility
View.STATUS_BAR_TRANSIENT————0x04000000
View.STATUS_BAR_TRANSLUCENT———-0x40000000
View.STATUS_BAR_TRANSPARENT———-0x0000008

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PanelView->flingToHeight
里面会创建一个动画进行height变化的动画
ValueAnimator animator = createHeightAnimator(target);

<think>我们正在讨论的是在Android 14中如何实现SystemUIStatusBar重建。根据之前的知识,我们知道SystemUI在主题切换等情况下可能需要重建。但用户特别询问了StatusBar的重建方法,并且是在Android 14上。 参考引用: [^1] 提到了SystemUI的基本布局设计StatusBar类的启动过程,以及三个窗口的创建。 [^2] 详细描述了StatusBar的创建过程:根据布局文件创建StatusBarWindowView,填充CollapsedStatusBarFragment,创建导航栏(针对CarStatusBar),并将StatusBarWindowView添加到WindowManager。 [^3] 展示了如何设置状态栏的样式,包括设置状态栏文字图标颜色、去除状态栏背景、设置状态栏透明等。 [^4] 提到了兼容性处理,比如使用Support库来支持旧版本。 [^5] 讨论了透明方案的问题,比如设置透明后引起的动画问题、固定屏幕方向冲突等。 用户需求:在Android 14中实现StatusBar的重建。 重建StatusBar的原因可能是主题切换、配置变更(如屏幕旋转)等。在SystemUI中,StatusBar是一个核心组件,它由SystemUIApplication启动,并在配置变化时可能会被重建。 重建StatusBar的步骤: 1. 销毁当前的StatusBar实例(包括其视图相关的Fragment)。 2. 重新创建StatusBar实例,并重新初始化视图状态。 3. 将新的StatusBar视图添加到WindowManager。 但是,在Android 14中,SystemUI的重建机制可能已经有所变化。我们需要考虑如何在不重启整个SystemUI进程的情况下重建StatusBar。 参考之前的回答,我们提到了在SystemUIApplication中监听配置变更并重启SystemUI,但这会重启整个进程。而用户可能希望只重建StatusBar。 因此,我们可以考虑在StatusBar内部实现重建。例如,当主题改变时,我们可以移除当前StatusBar的所有视图,然后重新创建它们。 具体步骤: 1.StatusBar类中提供一个重建方法(例如recreateStatusBar())。 2. 在这个方法中,首先移除当前StatusBar的所有视图(通过StatusBarWindowView)。 3. 然后重新调用初始化视图的方法(例如inflateViews())。 4. 重新设置状态栏的各个部分(如通知面板、快捷设置等)。 5. 更新状态栏的样式(如颜色、图标样式等)。 但是,由于StatusBar内部包含多个组件(如CollapsedStatusBarFragment、NotificationPanelViewController等),重建过程需要小心处理,避免内存泄漏视图状态不一致。 另外,我们还需要考虑系统服务(如WindowManager)的重新绑定。 参考[^2]中提到的StatusBar创建过程,我们可以将初始化代码封装,以便重建时调用。 示例代码(伪代码): ```java public class StatusBar extends SystemUI { private StatusBarWindowView mStatusBarWindowView; private CollapsedStatusBarFragment mCollapsedStatusBarFragment; @Override public void start() { super.start(); createAndAddStatusBarWindow(); } // 创建并添加StatusBarWindow private void createAndAddStatusBarWindow() { // 1. 根据布局创建StatusBarWindowView mStatusBarWindowView = (StatusBarWindowView) View.inflate(mContext, R.layout.super_status_bar, null); // 2.StatusBarWindowView添加到WindowManager mWindowManager.addView(mStatusBarWindowView, getStatusBarLayoutParams()); // 3. 初始化各个部分,例如CollapsedStatusBarFragment FragmentHostFragment fragmentHost = (FragmentHostFragment) mStatusBarWindowView .findViewById(R.id.status_bar_fragment_container).getFragment(); mCollapsedStatusBarFragment = new CollapsedStatusBarFragment(); fragmentHost.getFragmentManager().beginTransaction() .replace(R.id.status_bar_container, mCollapsedStatusBarFragment, TAG) .commit(); // ... 其他初始化 } // 重建StatusBar public void recreateStatusBar() { // 移除旧的视图 if (mStatusBarWindowView != null) { mWindowManager.removeView(mStatusBarWindowView); mStatusBarWindowView = null; } // 重新创建 createAndAddStatusBarWindow(); } } ``` 但是,直接移除整个StatusBarWindowView并重新添加可能会导致界面闪烁,而且可能影响其他系统组件(如通知面板)。因此,我们可以考虑只更新StatusBar的内容,而不是整个窗口。 另一种更精细的重建方法:只重新创建CollapsedStatusBarFragment。 在StatusBar中,我们可以只替换Fragment: ```java public void recreateStatusBar() { // 获取FragmentManager FragmentHostFragment fragmentHost = ...; FragmentManager fm = fragmentHost.getFragmentManager(); // 移除旧的Fragment Fragment oldFragment = fm.findFragmentByTag(TAG); if (oldFragment != null) { fm.beginTransaction().remove(oldFragment).commitNow(); } // 创建新的Fragment mCollapsedStatusBarFragment = new CollapsedStatusBarFragment(); fm.beginTransaction().replace(R.id.status_bar_container, mCollapsedStatusBarFragment, TAG).commit(); // 重新应用主题 applyTheme(); } ``` 在Android 14中,可能还需要考虑新的API系统特性。例如,Material You动态取色可能需要额外的处理。 另外,重建时需要注意状态同步(如当前的通知、系统图标等)。因此,重建过程中需要重新绑定数据。 注意事项: 1. 重建时,需要保存当前状态(如是否展开通知面板、亮度条位置等)并在重建后恢复。 2. 避免在重建过程中出现ANR,因此耗时操作应异步执行。 3. 主题切换时,系统会发送配置变更(ConfigurationChange),我们可以监听此事件来触发重建。 在StatusBar中监听配置变更: ```java @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (isThemeChanged(newConfig)) { recreateStatusBar(); } } ``` 但是,注意配置变更可能频繁发生(如屏幕旋转),因此需要确保重建操作不会过于频繁。 总结: 在Android 14中,我们可以通过重新创建StatusBar的视图(或部分视图)来实现重建。具体步骤包括移除旧的视图或Fragment,然后重新创建并添加。同时,需要处理状态保存恢复,以及避免性能问题。 由于SystemUI是系统核心应用,修改需要系统签名,并且需要谨慎测试。 下面,我们将按照步骤详细说明。</think>在 Android 14 中实现 SystemUI StatusBar 重建,需要结合资源动态加载、视图销毁重建配置更新机制。以下是具体实现方案: --- ### **一、StatusBar 重建核心流程** #### 1. **销毁现有 StatusBar 视图** ```java // StatusBar.java public void destroyStatusBar() { // 移除状态栏容器视图 if (mStatusBarContainer != null) { mWindowManager.removeView(mStatusBarContainer); // 引用[2] } // 清理 Fragment FragmentManager fm = getSupportFragmentManager(); Fragment fragment = fm.findFragmentById(R.id.status_bar_container); if (fragment != null) { fm.beginTransaction().remove(fragment).commitNow(); // 引用[4] } // 释放资源 mNotificationPanelViewController = null; mCollapsedStatusBarFragment = null; } ``` #### 2. **重建 StatusBar 视图** ```java // StatusBar.java public void recreateStatusBar() { // 1. 创建新容器视图 mStatusBarContainer = (StatusBarWindowView) LayoutInflater.from(this) .inflate(R.layout.super_status_bar, null); // 引用[2] // 2. 添加状态栏容器到 WindowManager mWindowManager.addView(mStatusBarContainer, createLayoutParams()); // 3. 重建 CollapsedStatusBarFragment FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.status_bar_container, new CollapsedStatusBarFragment(), "status_bar"); ft.commitNow(); // 引用[4] // 4. 重新初始化关键组件 mNotificationPanelViewController = new NotificationPanelViewController( mStatusBarContainer.findViewById(R.id.notification_panel) ); } ``` #### 3. **主题应用与配置更新** ```java // 应用新主题配置 public void applyNewTheme(int themeResId) { // 更新系统 UI 标志 int systemUiVisibility = mDecorView.getSystemUiVisibility(); systemUiVisibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // 引用[3] mDecorView.setSystemUiVisibility(systemUiVisibility); // 设置状态栏透明 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); getWindow().setStatusBarColor(Color.TRANSPARENT); // 引用[3] // 应用主题样式 getTheme().applyStyle(themeResId, true); } ``` --- ### **二、Android 14 适配关键点** #### 1. **使用 `ComponentCallbacks2` 监听配置变更** ```java public class StatusBar extends SystemUI implements ComponentCallbacks2 { @Override public void onConfigurationChanged(Configuration newConfig) { if (isThemeConfigChanged(newConfig)) { destroyStatusBar(); recreateStatusBar(); } } private boolean isThemeConfigChanged(Configuration config) { return (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) != (mLastConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK); } } ``` #### 2. **Material You 动态取色集成** ```java // 应用 Monet 引擎取色 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { MonetWannabe monet = new MonetWannabe(getContext()); monet.setColorScheme(new MonetWannabe.ColorScheme( getResources().getColor(android.R.color.system_neutral1_800), getResources().getColor(android.R.color.system_accent1_200) )); monet.apply(); } ``` #### 3. **避免窗口闪烁的优化** ```diff - mWindowManager.removeView(mStatusBarContainer); - mWindowManager.addView(newContainer, params); + // 使用视图替换避免窗口闪烁 + ViewGroup parent = (ViewGroup) mStatusBarContainer.getParent(); + int index = parent.indexOfChild(mStatusBarContainer); + parent.removeView(mStatusBarContainer); + parent.addView(newContainer, index, params); // 引用[5]优化 ``` --- ### **三、完整调用示例** ```java // ThemeSwitchController.java public void switchTheme(int themeResId) { // 1. 保存主题配置 Settings.System.putInt(mContentResolver, "systemui_theme", themeResId); // 2. 触发重建 mStatusBar.destroyStatusBar(); mStatusBar.applyNewTheme(themeResId); mStatusBar.recreateStatusBar(); // 3. 发送广播通知其他组件 Intent intent = new Intent("com.android.systemui.ACTION_THEME_CHANGED"); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } ``` --- ### **四、注意事项** 1. **窗口类型声明** ```xml <!-- status_bar.xml --> <com.android.systemui.statusbar.phone.StatusBarWindowView android:id="@+id/status_bar_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:windowType="2001" <!-- TYPE_STATUS_BAR --> android:systemUiVisibility=" SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN"/> ``` 2. **权限要求** ```xml <uses-permission android:name="android.permission.DUMP" /> <uses-permission android:name="android.permission.CONTROL_UI_TRANSLUCENCY" /> ``` 3. **Android 14 专属 API** ```java // 使用 WindowManager.LayoutParams#setFitInsetsTypes() if (Build.VERSION.SDK_INT >= 34) { params.setFitInsetsTypes(WindowInsets.Type.statusBars()); } ``` --- ### **性能优化建议** 1. **异步资源加载** ```java new AsyncTask<Void, Void, TypedArray>() { protected TypedArray doInBackground() { return res.obtainStyledAttributes(themeResId, R.styleable.StatusBarTheme); } protected void onPostExecute(TypedArray colors) { applyColors(colors); // 主线程更新 } }.execute(); ``` 2. **视图复用池** ```java private final SparseArray<View> mViewCache = new SparseArray<>(); View getCachedView(int layoutId) { View view = mViewCache.get(layoutId); if (view != null) { mViewCache.remove(layoutId); return view; } return LayoutInflater.from(mContext).inflate(layoutId, null); } ``` --- > StatusBar 重建涉及窗口管理、资源动态加载组件生命周期控制,核心是通过`WindowManager`移除并重新创建视图层级[^2]。Android 14 的`Monet`引擎可简化颜色适配流程[^1],但需注意透明状态栏引起的布局问题[^5]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值