Android13 关于SystemUI更新/Nav Bar add volume button&&other button

对比Android 11, Android 13的SystemUI的源码文件目录,部分文件位置移动了或者删除了,其它的做出了很多改变,变的更加清晰、模块化…
代码里面注解用的频繁了. Dragger2是一个依赖注入框架,在编译期间自动生成代码,负责依赖对象的创建.
Dragger2

SystemUI初始化
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\CentralSurfacesImpl.java
    @Override
    public void start() {
    	...
        //statusBar相关,主要处理和信号有关的icon,比如mobile,wifi,vpn等
        mStatusBarSignalPolicy.init();
        ...
    	createAndAddWindows(result);//入口,添加view的核心函数
    	...
        //关于壁纸
        if (mWallpaperSupported) {
            // Make sure we always have the most current wallpaper info.
            IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
            mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter,
                    null /* handler */, UserHandle.ALL);
            mWallpaperChangedReceiver.onReceive(mContext, null);
        } else if (DEBUG) {
            Log.v(TAG, "start(): no wallpaper service ");
        }

        // Set up the initial notification state. This needs to happen before CommandQueue.disable()
        //初始化通知栏状态
        setUpPresenter();
        ...
        // Lastly, call to the icon policy to install/update all the icons.
        //状态栏上wifi,BT 等状态图标的更新
        mIconPolicy.init();
        ...
	}

    @Override
    public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
        makeStatusBarView(result);
        mNotificationShadeWindowController.attach();//添加通知
        mStatusBarWindowController.attach();//添加状态栏
    }
    
    protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
        updateDisplaySize(); // populates mDisplayMetrics
        updateResources();
        updateTheme();
        
        inflateStatusBarWindow();//状态栏初始化
        mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener());
        mWallpaperController.setRootView(mNotificationShadeWindowView);
        ...
        createNavigationBar(result);//导航栏初始化
        ...
    }
    
    protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
        mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
    }
 


    

NavigationBar详解
关于导航栏的创建,系统会判断屏幕大小来决定是否生成NavigationBar.如果屏幕过大导致判定为平板,
就会走Launcher3里面的/quickstep/taskbar 来替代导航栏.

frameworks\base\packages\SystemUI\src\com\android\systemui\navigationbar\NavigationBarController.java

    private boolean updateNavbarForTaskbar() {
        boolean taskbarShown = initializeTaskbarIfNecessary();
        if (!taskbarShown && mNavigationBars.get(mContext.getDisplayId()) == null) {
            createNavigationBar(mContext.getDisplay(), null, null);
        }
        return taskbarShown;
    }

    /** 平板:true */
    private boolean initializeTaskbarIfNecessary() {
        // Enable for tablet or (phone AND flag is set); assuming phone = !mIsTablet
        boolean taskbarEnabled = mIsTablet || mFeatureFlags.isEnabled(Flags.HIDE_NAVBAR_WINDOW);

        if (taskbarEnabled) {
            //是平板,移除屏幕上的navBar
            removeNavigationBar(mContext.getDisplayId());
            mTaskbarDelegate.init(mContext.getDisplayId());
        } else {
            mTaskbarDelegate.destroy();
        }
        return taskbarEnabled;
    }
    
    
    public void createNavigationBars(final boolean includeDefaultDisplay,
            RegisterStatusBarResult result) {
        updateAccessibilityButtonModeIfNeeded();

        // Don't need to create nav bar on the default display if we initialize TaskBar.
        final boolean shouldCreateDefaultNavbar = includeDefaultDisplay
                && !initializeTaskbarIfNecessary();
        Display[] displays = mDisplayTracker.getAllDisplays();
        for (Display display : displays) {
            if (shouldCreateDefaultNavbar
                    || display.getDisplayId() != mDisplayTracker.getDefaultDisplayId()) {
                createNavigationBar(display, null /* savedState */, result);
            }
        }
    }
    
    @VisibleForTesting
    void createNavigationBar(Display display, Bundle savedState, RegisterStatusBarResult result) {
        ...
    	//从这里分为两个部分
    	NavigationBar navBar = component.getNavigationBar();//导航栏实例化,navBar通过注解生成的
        navBar.init();//将导航栏添加到屏幕上
        mNavigationBars.put(displayId, navBar);
        ...
    }
    <!-- 分号隔开左中右,然后逗号隔开,w表示比重,A表示绝对值,C表示居中
        left和right,分别是space和menu_ime
    -->
    <string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string>
    <string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string>
    <string name="config_navBarLayoutHandle" translatable="false">back[70AC];home_handle;ime_switcher[70AC]</string>

Nav Bar add volume button(+,-)&&other button

1.config_navBarLayout配置更新

frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java

    protected String getDefaultLayout() {
        final int defaultResource = QuickStepContract.isGesturalMode(mNavBarMode)
                ? R.string.config_navBarLayoutHandle
                : mOverviewProxyService.shouldShowSwipeUpUI()
                        ? R.string.config_navBarLayoutQuickstep
                        : R.string.config_navBarLayout;
        return getContext().getString(defaultResource);
    }

+++ b/frameworks/base/packages/SystemUI/res/values/config.xml
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string>
+    <string name="config_navBarLayout" translatable="false">left[.5W];volume_sub,back,home,recent,volume_add;right[.5W]</string>

2.准备对应的布局资源文件

//要变成减音量,keyCode="25",其余不变; 自定义按键:systemui:keyCode="0",其余不变
/SystemUI/res/layout/volume_add.xml

<com.android.systemui.navigationbar.buttons.KeyButtonView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/volume_add"
    android:layout_width="@dimen/navigation_key_width"
    android:layout_height="match_parent"
    android:layout_weight="0"
    systemui:keyCode="24"
    android:scaleType="center"
    android:contentDescription="@string/accessibility_home"
    android:paddingStart="@dimen/navigation_key_padding"
    android:paddingEnd="@dimen/navigation_key_padding"
    />

SystemUI/res/drawable/ic_sysbar_volume_add_button.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="?attr/singleToneColor"
        android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
</vector>

SystemUI/res/drawable/ic_sysbar_volume_sub_button.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="28dp"
        android:height="28dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="?attr/singleToneColor"
        android:pathData="M18.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM5,9v6h4l5,5V4L9,9H5z"/>
</vector>

3.按钮加入Nav Bar

+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
@@ -68,7 +68,10 @@ public class NavigationBarInflaterView extends FrameLayout
     public static final String RIGHT = "right";
     public static final String CONTEXTUAL = "contextual";
     public static final String IME_SWITCHER = "ime_switcher";
+    //add text
+    public static final String VOLUME_ADD = "volume_add";
+    public static final String VOLUME_SUB = "volume_sub";
+    //add text
     public static final String GRAVITY_SEPARATOR = ";";
     public static final String BUTTON_SEPARATOR = ",";

@@ -387,6 +390,10 @@ public class NavigationBarInflaterView extends FrameLayout
             v = inflater.inflate(R.layout.home_handle, parent, false);
         } else if (IME_SWITCHER.equals(button)) {
             v = inflater.inflate(R.layout.ime_switcher, parent, false);
+        } else if (VOLUME_ADD.equals(button)) {
+            v = inflater.inflate(R.layout.volume_add, parent, false);
+        } else if (VOLUME_SUB.equals(button)) {
+            v = inflater.inflate(R.layout.volume_sub, parent, false);
         } else if (button.startsWith(KEY)) {
             String uri = extractImage(button);
             int code = extractKeycode(button);
  

+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -119,6 +119,10 @@ public class NavigationBarView extends FrameLayout {
     private KeyButtonDrawable mHomeDefaultIcon;
     private KeyButtonDrawable mRecentIcon;
     private KeyButtonDrawable mDockedIcon;
+    //add add xxx
+    private KeyButtonDrawable mVolumeAddIcon;
+    private KeyButtonDrawable mVolumeSubIcon;
+    //add xxx
     private Context mLightContext;
     private int mLightIconColor;
     private int mDarkIconColor;
@@ -323,6 +327,10 @@ public class NavigationBarView extends FrameLayout {
         mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
         mButtonDispatchers.put(R.id.accessibility_button, accessibilityButton);
         mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
+        //add add xxx
+        mButtonDispatchers.put(R.id.volume_add, new ButtonDispatcher(R.id.volume_add));
+        mButtonDispatchers.put(R.id.volume_sub, new ButtonDispatcher(R.id.volume_sub));
+        //add add xxx
         mDeadZone = new DeadZone(this);
     }

@@ -419,6 +427,16 @@ public class NavigationBarView extends FrameLayout {
         return mButtonDispatchers.get(R.id.home);
     }

+    //add add xxx
+    public ButtonDispatcher getVolumeAddButton() {
+        return mButtonDispatchers.get(R.id.volume_add);
+    }
+
+    public ButtonDispatcher getVolumeSubButton() {
+        return mButtonDispatchers.get(R.id.volume_sub);
+    }
+    //add xxx
+
     public ButtonDispatcher getImeSwitchButton() {
         return mButtonDispatchers.get(R.id.ime_switcher);
     }
@@ -471,6 +489,10 @@ public class NavigationBarView extends FrameLayout {
         if (orientationChange || densityChange || dirChange) {
             mBackIcon = getBackDrawable();
         }
+        //add add xxx
+        mVolumeAddIcon = getDrawable(R.drawable.ic_sysbar_volume_add_button);
+        mVolumeSubIcon = getDrawable(R.drawable.ic_sysbar_volume_sub_button);
+        //add xxx
     }

     /**
@@ -615,7 +637,10 @@ public class NavigationBarView extends FrameLayout {
         }
         getHomeButton().setImageDrawable(homeIcon);
         getBackButton().setImageDrawable(backIcon);
-
+        //add add xxx
+        getVolumeAddButton().setImageDrawable(mVolumeAddIcon);
+        getVolumeSubButton().setImageDrawable(mVolumeSubIcon);
+        //add xxx
         updateRecentsIcon();

         // Update IME button visibility, a11y and rotate button always overrides the appearance
@@ -1146,6 +1171,10 @@ public class NavigationBarView extends FrameLayout {

         dumpButton(pw, "back", getBackButton());
         dumpButton(pw, "home", getHomeButton());
+        //add add xxx
+        dumpButton(pw, "volume_add", getVolumeAddButton());
+        dumpButton(pw, "volume_sub", getVolumeSubButton());
+        //add xxx
         dumpButton(pw, "handle", getHomeHandle());
         dumpButton(pw, "rcnt", getRecentsButton());
         dumpButton(pw, "rota", getRotateSuggestionButton());

4.自定义按钮()的监听,无系统定义的keyCode,音量加减不用看这里
hide_nav布局模仿上面的顺序添加就行了.

+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java

+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.os.UserHandle;
+import android.provider.Settings;
  
+    //add text
+    private ContentResolver mContentResolver;
+    private ContentObserver mHideNavButtonShowObserver;
+    //add text

    
    //模仿这里面的点击操作
    private void prepareNavigationBarView() {
        mView.reorient();

        ButtonDispatcher recentsButton = mView.getRecentsButton();
        recentsButton.setOnClickListener(this::onRecentsClick);
        recentsButton.setOnTouchListener(this::onRecentsTouch);
        
+        //add text
+        ButtonDispatcher hideNavButton = mView.getHideNavButton();
+        hideNavButton.setOnClickListener(this::onHideNavClick);
+        boolean isShowNavHideButton = Settings.System.getInt(getContext().getContentResolver(), "hide_xx_status", 0) == 1;
+        if(isShowNavHideButton){
+            hideNavButton.setVisibility(View.VISIBLE);
+        }else{
+            hideNavButton.setVisibility(View.GONE);
+        }
+        //add text

        ...
        ButtonDispatcher accessibilityButton = mView.getAccessibilityButton();
        accessibilityButton.setOnClickListener(this::onAccessibilityClick);
        accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
        ...
    }
    
    //add text
+    private long mLastClickNavHideTime = 0;
+
+    private void onHideNavClick(View v){
+        long nowTime = SystemClock.elapsedRealtime();
+        if (nowTime - mLastClickNavHideTime < 2000) {
+            return;
+        }
+        Intent intent = new Intent("action_xx_xxx");
+        getContext().sendBroadcast(intent);
+        mLastClickNavHideTime = nowTime;
+    }
+    //add text

    @Override
    public void onInit() {
        mView.setBarTransitions(mNavigationBarTransitions);
        mView.setTouchHandler(mTouchHandler);
        ...
        //add text
        mContentResolver = getContext().getContentResolver();
        mHideNavButtonShowObserver = new ContentObserver(getContext().getMainThreadHandler()) {
            @Override
            public void onChange(boolean selfChange) {
                boolean isShowNavHideButton = Settings.System.getInt(getContext().getContentResolver(), "hide_xx_status", 0) == 1;
                ButtonDispatcher hideNavButton = mView.getHideNavButton();
                hideNavButton.setVisibility(isShowNavHideButton ? View.VISIBLE : View.GONE);
            }
        };
        mContentResolver.registerContentObserver(
                Settings.System.getUriFor("hide_xx_status"), true,
                mHideNavButtonShowObserver, UserHandle.USER_ALL);
        //add text
    
    }

    @Override
    public void onViewDetached() {
        mView.setUpdateActiveTouchRegionsCallback(null);
        getBarTransitions().destroy();
        ...
        //add text
        if(null != mHideNavButtonShowObserver){
            mContentResolver.unregisterContentObserver(mHideNavButtonShowObserver);
        }
        //add text
    }
    
    Region getButtonLocations(boolean includeFloatingButtons, boolean inScreenSpace,
            boolean useNearestRegion) {
        if (useNearestRegion && !inScreenSpace) {
            // We currently don't support getting the nearest region in anything but screen space
            useNearestRegion = false;
        }
        Region region = new Region();
        Map<View, Rect> touchRegionCache = mView.getButtonTouchRegionCache();
        updateButtonLocation(
                region, touchRegionCache, mView.getBackButton(), inScreenSpace, useNearestRegion);
        ...
        //add text
        updateButtonLocation(region, touchRegionCache, mView.getVolumeAddButton(), inScreenSpace,
                useNearestRegion);
        updateButtonLocation(region, touchRegionCache, mView.getVolumeSubButton(), inScreenSpace,
                useNearestRegion);
        //add text
        ...
        return region;
    }

Android导航栏音量调节
Android13系统导航栏添加音量加减键按钮功能
android framework13-SystemUI

禁止下拉状态栏菜单
/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
    public boolean panelsEnabled() {
-        final int disabled1 = getDisabled1(mDisplayTracker.getDefaultDisplayId());
-        final int disabled2 = getDisabled2(mDisplayTracker.getDefaultDisplayId());
-        return (disabled1 & StatusBarManager.DISABLE_EXPAND) == 0
-                && (disabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0;
+
+        return false;
    }
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个类是在 Android 系统中负责实现状态栏的显示和管理的。具体来说,它定义了一个 CentralSurfaces 类来管理状态栏的中央表面,该表面包含状态栏图标、通知和快捷设置等元素。CentralSurfaces 类实现了多个接口,包括 ViewTreeObserver.OnPreDrawListener 和 DisplayManager.DisplayListener 等,通过这些接口来监听状态栏中各个元素的状态变化,并及时更新状态栏的显示内容。此外,CentralSurfaces 还负责管理状态栏的显示位置、大小和透明度等属性,确保其与其他应用程序的界面不会产生冲突。 ### 回答2: CentralSurfaces.java 是 Android 系统中的一个类,位于 frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/ 目录下,主要用于处理手机状态栏的中央面板(Central Panel)。 手机状态栏是 Android 系统中的一个重要组件,它位于屏幕的顶部,并显示系统的各种信息和通知。Central Panel 是状态栏中的一个重要部分,它包含了一些常用的控件和功能,如时间、信号强度、电量等。 CentralSurfaces.java 这个类的作用是管理和绘制 Central Panel 所需要的 Surface(表面)。Surface 是 Android 中用于显示 UI 元素的基本单位,可以理解为一个平面的画布,上面可以绘制各种组件和内容。 CentralSurfaces.java 类中的方法主要涉及到 Central Panel 上的 Surface 的创建、更新和销毁等操作。它负责监听状态栏的变化,并根据变化来更新 Central Panel 的画布,确保 Central Panel 的内容和样式与系统状态同步。 此外,CentralSurfaces.java 类还处理了 Central Panel 的触摸事件,以及点击事件的分发和处理。当用户在 Central Panel 上进行触摸操作时,它会负责捕获触摸事件,并对触摸事件进行解析,然后将事件传递给对应的处理模块。 总之,CentralSurfaces.java 类是 Android 系统中负责管理状态栏中央面板(Central Panel)的 Surface 绘制和事件处理的类,它确保 Central Panel 的绘制和交互能够与系统状态进行同步。 ### 回答3: CentralSurfaces.java是Android 13SystemUI模块中的一个类,主要用于管理状态栏和导航栏的中心表面。 在Android系统中,状态栏是用户界面的一部分,用于显示通知、系统图标和其他相关信息。导航栏则用于用户导航和操作。CentralSurfaces.java的主要作用是为状态栏和导航栏提供统一的管理和绘制。 具体来说,CentralSurfaces.java类负责管理状态栏和导航栏中心表面的创建、更新和销毁。它通过与其他系统UI组件进行交互,确保状态栏和导航栏与其他应用程序、窗口和系统元素的显示无冲突,并且能够正确响应用户的操作。 该类还负责跟踪状态栏和导航栏的布局和外观变化,并相应地更新中心表面的显示。它可以根据不同的设备或系统配置来适应不同的屏幕大小和分辨率。 总体而言,CentralSurfaces.java是SystemUI模块中的一个关键类,负责管理和绘制状态栏和导航栏的中心表面,以提供良好的用户体验和操作响应能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值