当前位置:   article > 正文

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

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

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

#### 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详解](https://juejin.cn/post/7223216421199315000)
关于导航栏的创建,系统会判断屏幕大小来决定是否生成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导航栏音量调节](https://blog.csdn.net/qq_27636049/article/details/103632949)
[Android13系统导航栏添加音量加减键按钮功能](https://blog.csdn.net/wzh048503/article/details/140020452)
[android framework13-SystemUI](https://juejin.cn/post/7223192684126535735)

#### 禁止下拉状态栏菜单
```
/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;
    }
```

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/970478
推荐阅读
相关标签
  

闽ICP备14008679号