Android系统 添加动态控制SystemUI状态栏、导航栏和下拉菜单

简介: Android系统 添加动态控制SystemUI状态栏、导航栏和下拉菜单

在Android系统中,状态栏(StatusBar)、导航栏(NavigationBar)和下拉菜单(ExPlan)是三个常见的用户界面元素,它们分别提供了一些基本的信息显示和交互功能。例如,状态栏可以显示时间、电量、信号等信息,导航栏可以提供返回、主页、多任务等按钮,下拉菜单可以提供快速设置、通知等选项。并不是所有客户的Android设备都需要或支持这些,有时候客户可能想要自由地控制它们的显示和隐藏。

本文将介绍如何在Android系统中定制添加状态栏、导航栏和下拉菜单的控制功能,以便客户可以根据需求使用。

实现步骤

要实现状态栏、导航栏和下拉菜单的控制功能,需要修改以下几个部分:

  • SystemUI模块:这是一个系统应用程序,负责显示和管理状态栏、导航栏和下拉菜单等界面元素。
  • Settings模块:这是一个系统应用程序,负责提供各种系统设置选项,包括显示设置。
  • 系统属性:这是一种用于存储和传递系统配置信息的机制,可以通过命令行或代码来读写。
  • 广播:这是一种用于在不同组件之间传递消息的机制,可以通过命令行或代码来发送和接收。

需要完成以下几个步骤:

  1. 在SystemUI模块中添加广播接收器,用于接收控制状态栏、导航栏和下拉菜单显示和隐藏的广播,并执行相应的操作。
  2. 在SystemUI模块中添加系统属性读取,用于获取状态栏、导航栏和下拉菜单的初始状态,并创建或移除相应的界面元素。
  3. 在Settings模块中添加开关偏好项,用于控制状态栏、导航栏和下拉菜单的开启和关闭,并发送相应的广播,并写入相应的系统属性。
  4. 编译并运行修改后的系统,并在设置中测试控制功能。

修改示例

SystemUI模块

frameworks/base/packages/SystemUI/AndroidManifest.xml

在SystemUI模块的AndroidManifest.xml文件中 需要添加以下几行代码,用于声明要接收的广播:

<protected-broadcast android:name="sys.explan.show" />
    <protected-broadcast android:name="sys.explan.hide" />
    
    <protected-broadcast android:name="sys.statusbar.show" />
    <protected-broadcast android:name="sys.statusbar.hide" />
    <protected-broadcast android:name="sys.navigationbar.show" />
    <protected-broadcast android:name="sys.navigationbar.hide" />
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java

在SystemUI模块的NavigationBarController.java文件中需要添加一个函数,用于移除所有的导航栏:

public void removeNavigationBars() {
        Display[] displays = mDisplayManager.getDisplays();
        for (Display display : displays) {
            removeNavigationBar(display.getDisplayId());
        }
    }
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java

在SystemUI模块的PhoneStatusBarView.java文件中需要修改,用于根据系统属性来决定是否响应下拉菜单的触摸事件:

(这个文件如果用于动态控制 有bug,除了这个文件其他都正常修改 )

-        return barConsumedEvent || super.onTouchEvent(event);
+       /* String value = SystemProperties.get("persist.sys.explan.enable", "false");
+        if(value.equals("true")){
+          return barConsumedEvent || super.onTouchEvent(event);
+        }else{
+          return true;  
+        }*/
+        //
+          return barConsumedEvent || super.onTouchEvent(event);
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

在SystemUI模块的StatusBar.java文件中,我们需要添加以下几行代码,用于声明和初始化一些变量和方法:

+     private static final String ACTION_HIDE_EXPLAN = "sys.explan.hide";
+     private static final String ACTION_SHOW_EXPLAN = "sys.explan.show";
+     private static final String ACTION_HIDE_STATUS_BAR = "sys.statusbar.hide";
+     private static final String ACTION_SHOW_STATUS_BAR = "sys.statusbar.show";
+     private static final String ACTION_HIDE_NAVIGATION_BAR = "sys.navigationbar.hide";
+     private static final String ACTION_SHOW_NAVIGATION_BAR = "sys.navigationbar.show";
+     private static final String SYS_PROPERTY_STATUS_BAR = "persist.sys.statusbar.enable";
+     private static final String SYS_PROPERTY_NAVIGATION_BAR = "persist.sys.navigationbar.enable";
+     private static final String SYS_PROPERTY_EXPLAN = "persist.sys.explan.enable";
+     protected StatusBarManager mStatusBarManager;
+
      public StatusBar(Context context) {
          super(context);
          ...
+         mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
          ...
      }
+
+  public void explan_show() {
+        mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);
+   }
+   public void explan_hide() {
+        mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
+   }

在SystemUI模块的StatusBar.java文件中,还需要修改以下几行代码,用于根据系统属性来决定初始化是否创建或隐藏状态栏、导航栏和下拉菜单:

-        createAndAddWindows(result);
-
+        //ln28_add_start
+        if (!SystemProperties.getBoolean(SYS_PROPERTY_STATUS_BAR, false)) {
+            mStatusBarWindowController.setBarVisibility(View.GONE);
+        }
+        //ln28_add_end
         if (mWallpaperSupported) {
             ...
         }
-
-        createNavigationBar(result);
-
+        //ln28_add_start
+        if (SystemProperties.getBoolean(SYS_PROPERTY_NAVIGATION_BAR, false)) {
+            createNavigationBar(result);
+        }
+        if (SystemProperties.getBoolean(SYS_PROPERTY_EXPLAN, false)) {
+            explan_show();
+        }
+        //ln28_add_end
         if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) {
             ...
         }

在SystemUI模块的StatusBar.java文件中,还还需要添加以下几行代码,用于注册和处理我们要接收的广播 实现逻辑动态控制:

filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
+        filter.addAction(ACTION_HIDE_NAVIGATION_BAR);
+        filter.addAction(ACTION_SHOW_NAVIGATION_BAR);
+        filter.addAction(ACTION_HIDE_STATUS_BAR);
+        filter.addAction(ACTION_SHOW_STATUS_BAR);
+        filter.addAction(ACTION_HIDE_EXPLAN);
+        filter.addAction(ACTION_SHOW_EXPLAN);
         mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
     }
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
                 ...
             } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 ...
             } else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) {
                 mQSPanel.showDeviceMonitoringDialog();
+            } else if (ACTION_HIDE_NAVIGATION_BAR.equals(action)) {
+                mNavigationBarController.removeNavigationBars();
+                SystemProperties.set(SYS_PROPERTY_NAVIGATION_BAR, "false");
+            } else if (ACTION_SHOW_NAVIGATION_BAR.equals(action)) {
+                createNavigationBar(null);
+                SystemProperties.set(SYS_PROPERTY_NAVIGATION_BAR, "true");
+            } else if (ACTION_HIDE_STATUS_BAR.equals(action)) {
+                mStatusBarWindowController.setBarVisibility(View.GONE);
+                SystemProperties.set(SYS_PROPERTY_STATUS_BAR, "false");
+            } else if (ACTION_SHOW_STATUS_BAR.equals(action)) {
+                mStatusBarWindowController.setBarVisibility(View.VISIBLE);
+                SystemProperties.set(SYS_PROPERTY_STATUS_BAR, "true");
+            } else if (ACTION_HIDE_EXPLAN.equals(action)) {
+                explan_hide();
+                SystemProperties.set(SYS_PROPERTY_EXPLAN, "false");
+            } else if (ACTION_SHOW_EXPLAN.equals(action)) {
+                explan_show();
+                SystemProperties.set(SYS_PROPERTY_EXPLAN, "true");
             }
         }
     };

OK 到这我们就完成了SystemUI模块的修改,是不是很简单? 接下来我们需要修改Settings模块。

Settings模块

packages/apps/Settings/res/values/strings.xml

在Settings模块的strings.xml文件中,需要添加以下几行代码,用于定义我们要显示的开关偏好项的标题:

<string name="ctrl_statusbar">状态栏</string>
    <string name="ctrl_explan">下拉菜单</string>
    <string name="ctrl_navigationbar">导航栏</string>
packages/apps/Settings/res/xml/display_settings.xml

在Settings模块的display_settings.xml文件中,需要添加以下几行代码,用于创建我们要显示的开关偏好项,并指定它们的键值和标题:

<SwitchPreference
       android:key="ctrl_statusbar"
       android:title="@string/ctrl_statusbar"/>
   <SwitchPreference
       android:key="ctrl_navigationbar"
       android:title="@string/ctrl_navigationbar"/>
   <SwitchPreference
       android:key="ctrl_explan"
       android:title="@string/ctrl_explan"/>
packages/apps/Settings/src/com/android/settings/DisplaySettings.java

在Settings模块的DisplaySettings.java文件中,需要添加以下几行代码,用于注册我们要控制的开关偏好项的控制器:

controllers.add(new ThemePreferenceController(context));
        controllers.add(new BrightnessLevelPreferenceController(context, lifecycle));
        controllers.add(new HdmiSettingsPreferenceController(context, KET_HDMI_SETTINGS));
+        controllers.add(new StatusBarPreferenceController(context));
+        controllers.add(new NavigationBarPreferenceController(context));
+        controllers.add(new ExPlanPreferenceController(context));
packages/apps/Settings/src/com/android/settings/display/StatusBarPreferenceController.java

在Settings模块的StatusBarPreferenceController.java文件中,需要添加以下几行代码,用于实现状态栏开关偏好项的控制器,主要负责读取和写入系统属性,以及发送控制广播:

package com.android.settings.display;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import android.content.Intent;
import android.util.Log;
import android.os.SystemProperties;
public class StatusBarPreferenceController extends AbstractPreferenceController implements
        Preference.OnPreferenceChangeListener {
    private static final String TAG = "StatusBarCtrl";
    private static final boolean DEBUG = true;
    private static final String KEY_STATUS_BAR = "ctrl_statusbar";
    private static final String SYS_PROP_STATUS_BAR_ENABLE = "persist.sys.statusbar.enable";
    public static final String ACTION_HIDE_STATUS_BAR = "sys.statusbar.hide";
    public static final String ACTION_SHOW_STATUS_BAR = "sys.statusbar.show";
    public StatusBarPreferenceController(Context context) {
        super(context);
    }
    @Override
    public String getPreferenceKey() {
        return KEY_STATUS_BAR;
    }
    @Override
    public boolean isAvailable() {
        return true;
    }
    @Override
    public void displayPreference(PreferenceScreen screen) {
        if (!isAvailable()) {
            setVisible(screen, KEY_STATUS_BAR, false);
            return;
        }
        final SwitchPreference mStatusBarPreference = screen.findPreference(KEY_STATUS_BAR);
        if (mStatusBarPreference != null) {
            String value = SystemProperties.get(SYS_PROP_STATUS_BAR_ENABLE, "false");
            mStatusBarPreference.setChecked(value.equals("true"));
            mStatusBarPreference.setOnPreferenceChangeListener(this);
        }
    }
    @Override
    public void updateState(Preference preference) {
        String value = SystemProperties.get(SYS_PROP_STATUS_BAR_ENABLE, "false");
        ((SwitchPreference) preference).setChecked(value.equals("true"));
    }
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        boolean value = (Boolean) newValue;
        if (DEBUG) {
            Log.d(TAG, "key value " + value);
        }
        Intent intent = new Intent();
        if (value) {
            intent.setAction(ACTION_SHOW_STATUS_BAR);
        } else {
            intent.setAction(ACTION_HIDE_STATUS_BAR);
        }
        mContext.sendBroadcast(intent);
        return true;
    }
}
packages/apps/Settings/src/com/android/settings/display/NavigationBarPreferenceController.java

在Settings模块的NavigationBarPreferenceController.java文件中,需要添加以下几行代码,用于实现导航栏开关偏好项的控制器,主要负责读取和写入系统属性,以及发送控制广播:

package com.android.settings.display;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import android.content.Intent;
import android.util.Log;
import android.os.SystemProperties;
public class NavigationBarPreferenceController extends AbstractPreferenceController
        implements Preference.OnPreferenceChangeListener {
    private static final String TAG = "NavigationBarCtrl";
    private static final boolean DEBUG = true;
    private static final String KEY_NAVIGATION_BAR = "ctrl_navigationbar";
    private static final String SYS_PROP_NAVIGATION_BAR_ENABLE = "persist.sys.navigationbar.enable"; 
    public static final String ACTION_HIDE_NAVIGATION_BAR = "sys.navigationbar.hide";
    public static final String ACTION_SHOW_NAVIGATION_BAR = "sys.navigationbar.show";
    public NavigationBarPreferenceController(Context context) {
        super(context);
    }
    @Override
    public String getPreferenceKey() {
        return KEY_NAVIGATION_BAR;
    }
    @Override
    public boolean isAvailable() {
        return true;
    }
    @Override
    public void displayPreference(PreferenceScreen screen) {
        if (!isAvailable()) {
            setVisible(screen, KEY_NAVIGATION_BAR, false);
            return;
        }
        final SwitchPreference mNavigationBarPreference = screen.findPreference(KEY_NAVIGATION_BAR);
        if (mNavigationBarPreference != null) {
            String value = SystemProperties.get(SYS_PROP_NAVIGATION_BAR_ENABLE, "false");
            mNavigationBarPreference.setChecked(value.equals("true"));
            mNavigationBarPreference.setOnPreferenceChangeListener(this);
        }
    }
    @Override
    public void updateState(Preference preference) {
        String value = SystemProperties.get(SYS_PROP_NAVIGATION_BAR_ENABLE, "false");
        ((SwitchPreference) preference).setChecked(value.equals("true"));
    }
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        boolean value = (Boolean) newValue;
        if (DEBUG) {
            Log.d(TAG, "key value " + value);
        }
        Intent intent = new Intent();
        if (value) {
            intent.setAction(ACTION_SHOW_NAVIGATION_BAR);
        } else {
            intent.setAction(ACTION_HIDE_NAVIGATION_BAR);
        }
        mContext.sendBroadcast(intent);
        return true;
    }
}
packages/apps/Settings/src/com/android/settings/display/ExPlanPreferenceController.java

在Settings模块的ExPlanPreferenceController.java文件中,需要添加以下几行代码,用于实现下拉菜单开关偏好项的控制器,主要负责读取和写入系统属性,以及发送控制广播:

package com.android.settings.display;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import android.content.Intent;
import android.util.Log;
import android.os.SystemProperties;
public class ExPlanPreferenceController extends AbstractPreferenceController implements
        Preference.OnPreferenceChangeListener {
    private static final String TAG = "ExPlanCtrl";
    private static final boolean DEBUG = true;
    private static final String KEY_EXPLAN = "ctrl_explan";
    private static final String SYS_PROP_EXPLAN_ENABLE = "persist.sys.explan.enable";
    private static final String ACTION_HIDE_EXPLAN = "sys.explan.hide";
    private static final String ACTION_SHOW_EXPLAN = "sys.explan.show";
    public ExPlanPreferenceController(Context context) {
        super(context);
    }
    @Override
    public String getPreferenceKey() {
        return KEY_EXPLAN;
    }
    @Override
    public boolean isAvailable() {
        return true;
    }
    @Override
    public void displayPreference(PreferenceScreen screen) {
        if (!isAvailable()) {
            setVisible(screen, KEY_EXPLAN, false);
            return;
        }
        final SwitchPreference mExPlanPreference = screen.findPreference(KEY_EXPLAN);
        if (mExPlanPreference != null) {
            String value = SystemProperties.get(SYS_PROP_EXPLAN_ENABLE, "false");
            mExPlanPreference.setChecked(value.equals("true"));
            mExPlanPreference.setOnPreferenceChangeListener(this);
        }
    }
    @Override
    public void updateState(Preference preference) {
        String value = SystemProperties.get(SYS_PROP_EXPLAN_ENABLE, "false");
        ((SwitchPreference) preference).setChecked(value.equals("true"));
    }
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        boolean value = (Boolean) newValue;
        if (DEBUG) {
            Log.d(TAG, "key value " + value);
        }
        Intent intent = new Intent();
        if (value) {
            intent.setAction(ACTION_SHOW_EXPLAN);
        } else {
            intent.setAction(ACTION_HIDE_EXPLAN);
        }
        mContext.sendBroadcast(intent);
        
        return true;
    }
}

这样就完成了Settings模块的修改,接下来直接编译并运行修改后的系统,并在设置中测试控制功能。

测试结果

以下是我在模拟器上测试的结果,您可以看到状态栏、导航栏和下拉菜单的显示和隐藏效果:

这是全部关闭的效果

这是全部打开的效果

重启后看到设置保存 到此, 需求实现完毕。

忘记了 如果要设置属性默认值你们自己随便找个位置添加就OK了。

+PRODUCT_PROPERTY_OVERRIDES += persist.sys.statusbar.enable=true
+PRODUCT_PROPERTY_OVERRIDES += persist.sys.navigationbar.enable=true
+PRODUCT_PROPERTY_OVERRIDES += persist.sys.explan.enable=true

结语

本文介绍了如何在Android系统中添加状态栏、导航栏和下拉菜单的控制功能,主要涉及了SystemUI模块和Settings模块的修改,以及系统属性和广播的使用。这些功能可以让用户控制和调用决定是否启用显示xx。

希望本文对你有所帮助,如果有任何问题或建议,请私信和留言。

相关文章
|
2月前
|
人工智能 搜索推荐 物联网
Android系统版本演进与未来展望####
本文深入探讨了Android操作系统从诞生至今的发展历程,详细阐述了其关键版本迭代带来的创新特性、用户体验提升及对全球移动生态系统的影响。通过对Android历史版本的回顾与分析,本文旨在揭示其成功背后的驱动力,并展望未来Android可能的发展趋势与面临的挑战,为读者呈现一个既全面又具深度的技术视角。 ####
|
2月前
|
IDE Java 开发工具
移动应用与系统:探索Android开发之旅
在这篇文章中,我们将深入探讨Android开发的各个方面,从基础知识到高级技术。我们将通过代码示例和案例分析,帮助读者更好地理解和掌握Android开发。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。让我们一起开启Android开发的旅程吧!
|
1月前
|
监控 Java Android开发
深入探索Android系统的内存管理机制
本文旨在全面解析Android系统的内存管理机制,包括其工作原理、常见问题及其解决方案。通过对Android内存模型的深入分析,本文将帮助开发者更好地理解内存分配、回收以及优化策略,从而提高应用性能和用户体验。
|
1月前
|
存储 安全 Android开发
探索Android系统的最新安全特性
在数字时代,智能手机已成为我们生活中不可或缺的一部分。随着技术的不断进步,手机操作系统的安全性也越来越受到重视。本文将深入探讨Android系统最新的安全特性,包括其设计理念、实施方式以及对用户的影响。通过分析这些安全措施如何保护用户免受恶意软件和网络攻击的威胁,我们希望为读者提供对Android安全性的全面了解。
|
2月前
|
监控 Java Android开发
深入探讨Android系统的内存管理机制
本文将深入分析Android系统的内存管理机制,包括其内存分配、回收策略以及常见的内存泄漏问题。通过对这些方面的详细讨论,读者可以更好地理解Android系统如何高效地管理内存资源,从而提高应用程序的性能和稳定性。
98 16
|
2月前
|
安全 Android开发 iOS开发
深入探讨Android与iOS系统的差异及未来发展趋势
本文旨在深入分析Android和iOS两大移动操作系统的核心技术差异、用户体验以及各自的市场表现,进一步探讨它们在未来技术革新中可能的发展方向。通过对比两者的开放性、安全性、生态系统等方面,本文揭示了两大系统在移动设备市场中的竞争态势和潜在变革。
|
2月前
|
算法 JavaScript Android开发
|
Android开发
Android屏幕适配之状态栏导航栏半透明、全透明(5.0以上去阴影),方法多样
1.1 StatusBar半透明用StatusBarView实现(4.4以上有效) 1.2 StatusBar半透明用setStatusBarColor实现(5.0以上有效) 2.1 StatusBar全透明用fitSystemWindows实现(4.
4966 0
|
4天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
1月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
65 19

热门文章

最新文章