Android11.0隐藏状态栏及导航栏

本文详细介绍了在Android11.0系统中如何在设置中添加隐藏状态栏和导航栏的开关,包括设置全局变量、修改默认值、使用广播机制以及在SystemUI中处理相关操作,确保了暗色模式下的可见性。

隐藏状态栏及导航栏

本文描述Android11系统设置-显示中添加隐藏状态栏及导航栏开关及功能实现。

添加全局状态保存配置

在M(Android5.0)版本之前,SettingsProvider中系统设置是存储在settings.db数据库中;但是在L(Android6.0)之后,SettingsProvider中系统设置改为由xml存储在data分区,路径为 /data/system/users/0/:
settings_global.xml
settings_secure.xml
settings_system.xml

  1. Settings中添加全局变量,修改路径 /frameworks/base/core/java/android/provider/Settings.java;
public static final class Global extends NameValueTable{
   
   
  //********省略代码******
  
        /**
         * Hide Navigation.
         *
         * @hide
         */
        public static final String HIDE_NAVIGATION = "hide_navigation";

        /**
         * Hide StatusBar.
         *
         * @hide
         */
        public static final String HIDE_STATUSBAR = "hide_statusbar";
        
  //********省略代码******
}
  1. 添加开关默认值,修改路径 /frameworks/base/packages/SettingsProvider/res/values/defaults.xml;
<resources>
//********省略代码******
    <integer name="def_hide_navigation">0</integer>
    <integer name="def_hide_statusbar">0</integer>
//********省略代码******
</resources>
  1. 添加proto,修改路径 /frameworks/base/core/proto/android/providers/settings/global.proto;
//********省略代码******

    message Display {
   
   
        //********省略代码******
        optional SettingProto hide_navigation_on = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
        optional SettingProto hide_statusbar_on = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
    }

//********省略代码******
  1. 开关默认值加载,修改路径 /frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java;
//********省略代码******

private void loadGlobalSettings(SQLiteDatabase db){
   
   

       loadIntegerSetting(stmt, Settings.Global.HIDE_NAVIGATION, R.integer.def_hide_navigation);
       loadIntegerSetting(stmt, Settings.Global.HIDE_STATUSBAR, R.integer.def_hide_statusbar);

}

//********省略代码******
  1. 修改路径 /frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java;
//********省略代码******

        final long displayToken = p.start(GlobalSettingsProto.DISPLAY);
        //********省略代码******
        dumpSetting(s, p,
                Settings.Global.HIDE_NAVIGATION,
                GlobalSettingsProto.Display.HIDE_NAVIGATION_ON);
        dumpSetting(s, p,
                Settings.Global.HIDE_STATUSBAR,
                GlobalSettingsProto.Display.HIDE_STATUSBAR_ON);
        p.end(displayToken);

//********省略代码******

设备-显示中添加隐藏状态栏及隐藏导航栏开关

  1. 定义开关名称文字 修改路径 /packages/app/Settings/res/values/strings.xml
//********省略代码******

    <string name
<think>根据用户的问题,用户希望了解在Android 10中通过Framework显示和隐藏导航栏的实现流程。结合提供的引用信息,特别是引用[2]和引用[3],我们可以总结出实现这一功能的核心类和关键步骤。 引用[2]提到,在Android 10.0中,可以通过广播来控制SystemUI状态栏的动态显示和隐藏,核心类是`StatusBar.java`。引用[3]则提到在MTK Android 8.1中隐藏导航栏按键的功能实现,涉及`PhoneWindowManager.java`和`StatusBar.java`。虽然引用[3]是Android 8.1,但实现思路类似,可以作为参考。 在Android系统中,导航栏(Navigation Bar)是SystemUI的一部分,其显示和隐藏通常由系统服务(如`WindowManagerService`)和SystemUI共同管理。具体到Android 10,我们可以通过以下步骤实现: ### 1. **核心类分析** - **`PhoneWindowManager.java`**:位于`frameworks/base/services/core/java/com/android/server/policy/`,负责窗口管理策略,包括导航栏的显示和隐藏。 - **`StatusBar.java`**:位于`frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/`,负责状态栏导航栏的UI管理。 ### 2. **实现流程** - **发送广播**:通过广播机制通知SystemUI显示或隐藏导航栏。 - **接收广播**:在`StatusBar`中注册广播接收器,处理显示/隐藏导航栏的请求。 - **更新导航栏状态**:调用`StatusBar`中控制导航栏显示和隐藏的方法。 #### 具体步骤: 1. **定义广播Action**:在系统中定义两个广播Action,例如`ACTION_SHOW_NAVIGATION_BAR`和`ACTION_HIDE_NAVIGATION_BAR`。 2. **发送广播**:在需要控制导航栏的地方(如应用或系统服务)发送广播。 ```java // 发送显示导航栏广播 Intent showIntent = new Intent("com.android.systemui.ACTION_SHOW_NAVIGATION_BAR"); context.sendBroadcast(showIntent); // 发送隐藏导航栏广播 Intent hideIntent = new Intent("com.android.systemui.ACTION_HIDE_NAVIGATION_BAR"); context.sendBroadcast(hideIntent); ``` 3. **在`StatusBar`中注册广播接收器**:在`StatusBar.java`的初始化方法中注册广播接收器。 ```java public class StatusBar extends SystemUI { // ... @Override public void start() { // ... registerBroadcastReceiver(); } private void registerBroadcastReceiver() { IntentFilter filter = new IntentFilter(); filter.addAction("com.android.systemui.ACTION_SHOW_NAVIGATION_BAR"); filter.addAction("com.android.systemui.ACTION_HIDE_NAVIGATION_BAR"); mContext.registerReceiver(mBroadcastReceiver, filter); } private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if ("com.android.systemui.ACTION_SHOW_NAVIGATION_BAR".equals(action)) { showNavigationBar(); } else if ("com.android.systemui.ACTION_HIDE_NAVIGATION_BAR".equals(action)) { hideNavigationBar(); } } }; } ``` 4. **实现`showNavigationBar`和`hideNavigationBar`方法**:在`StatusBar`中控制导航栏的显示和隐藏。 ```java private void showNavigationBar() { // 获取导航栏控制器 NavigationBarController controller = getNavigationBarController(); if (controller != null) { // 显示导航栏 controller.showNavigationBar(); } } private void hideNavigationBar() { NavigationBarController controller = getNavigationBarController(); if (controller != null) { // 隐藏导航栏 controller.hideNavigationBar(); } } ``` 注意:`NavigationBarController`是SystemUI中管理导航栏的类,实际调用可能需要通过`NavigationBarView`或`NavigationBarFragment`。 5. **更新`PhoneWindowManager`策略(可选)**:如果需要系统级别的控制(例如在特定窗口显示时自动隐藏导航栏),则需要在`PhoneWindowManager`中修改策略。 ```java public class PhoneWindowManager { // ... // 隐藏导航栏 public void hideNavigationBar() { // 通过WindowManagerService更新系统UI可见性 mWindowManagerFuncs.hideNavigationBar(); } // 显示导航栏 public void showNavigationBar() { mWindowManagerFuncs.showNavigationBar(); } } ``` ### 3. **权限问题** - 由于涉及系统级操作,广播发送者需要具有系统权限(如`android.permission.EXPAND_STATUS_BAR`),或者将广播接收器设置为系统级(通过`android:protectionLevel="signature"`)。 ### 4. **系统UI可见性** - 导航栏的显示和隐藏最终是通过设置系统UI可见性标志来实现的,例如: ```java View decorView = getWindow().getDecorView(); int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; decorView.setSystemUiVisibility(uiOptions); ``` 但在SystemUI内部,通常通过`WindowManager`服务来全局控制。 以上流程基于Android 10的Framework实现。需要注意的是,不同设备厂商(如MTK)可能有定制化的实现,但核心原理一致。 [^1]: Android 11.0 framework默认沉浸式导航栏功能实现。 [^2]: Android 10.0 通过广播控制systemui状态栏动态显示和隐藏功能实现。 [^3]: MTK Android8.1隐藏导航栏按键功能实现。 §§相关问题§§ 1.Android 10中,如何通过adb命令控制导航栏的显示和隐藏? 2. 除了广播,还有哪些方法可以控制SystemUI组件的显示和隐藏? 3. 如何定制导航栏的布局和功能(例如添加自定义按钮)?</think>### Android 10 Framework 实现显示/隐藏导航栏流程 在 Android 10 中,导航栏的显示/隐藏主要通过 `WindowManagerService` 和 `SystemUI` 协同实现,核心流程如下: #### 1. **核心类与入口** - **`PhoneWindowManager.java`** 路径:`frameworks/base/services/core/java/com/android/server/policy/` 职责:处理窗口策略,接收显示/隐藏请求并更新系统 UI 标志。 - **`StatusBar.java`** 路径:`frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/` 职责:控制导航栏 UI 的渲染和状态更新[^2]。 #### 2. **显示/隐藏实现流程** ```mermaid graph TD A[请求入口] --> B{显示或隐藏} B -->|显示| C[PhoneWindowManager 更新系统标志] B -->|隐藏| C C --> D[WindowManagerService 通知 SystemUI] D --> E[StatusBar 更新导航栏视图] ``` ##### 具体步骤: 1. **请求接收** 通过广播或系统服务调用(如 `IWindowManager.hideNavigationBar()`)触发操作: ```java // 示例:发送广播控制导航栏 Intent intent = new Intent("com.android.systemui.ACTION_HIDE_NAVIGATION_BAR"); context.sendBroadcast(intent); ``` 2. **更新系统 UI 标志** 在 `PhoneWindowManager` 中修改系统 UI 可见性标志: ```java // PhoneWindowManager.java public void setNavigationBarVisibility(boolean visible) { int newVis = visible ? View.VISIBLE : View.GONE; mWindowManagerFuncs.updateSystemUiVisibility( SYSTEM_UI_FLAG_NAVIGATION_HIDDEN, newVis // 控制显隐 ); } ``` 3. **SystemUI 响应更新** `StatusBar` 接收 `SYSUI_MSG_UPDATE_NAVIGATION` 消息,更新导航栏视图: ```java // StatusBar.java public void updateNavigationBar(boolean show) { if (mNavigationBarView != null) { mNavigationBarView.setVisibility(show ? View.VISIBLE : View.GONE); } } ``` #### 3. **关键配置** - **沉浸式模式处理**:在 `PhoneWindowManager.applyImmersiveFlags()` 中处理全屏应用的导航栏隐藏逻辑。 - **手势交互**:Android 10 引入全屏手势,需在 `NavigationBarView` 中兼容手势检测[^3]。 #### 4. **权限与安全** - 系统级权限要求:调用者需持有 `android.permission.STATUS_BAR` 权限。 - 签名保护:广播 Action 建议使用签名级保护(`android:protectionLevel="signature"`)。 > **注意**:不同 OEM 厂商可能有定制实现(如 MTK 在 `SystemUI` 中添加手势检测逻辑[^3]),但核心流程一致。 [^1]: Android 11.0 framework默认沉浸式导航栏功能实现。 [^2]: Android 10.0 通过广播控制systemui状态栏动态显示和隐藏功能实现。 [^3]: MTK Android8.1隐藏导航栏按键功能实现。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值