Android 11.0 SystemUI 导航栏虚拟按键icon大小改变

目录

1.概述

2.SystemUI 导航栏虚拟按键icon大小改变的核心类

3.SystemUI 导航栏虚拟按键icon大小改变的核心功能分析和实现

     3.1关于加载导航栏的相关代码分析

3.2NavigationBarView的相关源码分析


1.概述

  在11.0的系统产品开发中,对应SystemUI的NavigationBar导航栏的定制化开发也是比较常见的功能,由于产品的小屏幕的,所以对于屏幕导航栏的三个虚拟按键需要做定制,产品需求要求对导航栏虚拟按键的宽高做调整,放大虚拟按键宽高,所以需要查看关键源码然后修改就好了

2.SystemUI 导航栏虚拟按键icon大小改变的核心类

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java

3.SystemUI 导航栏虚拟按键icon大小改变的核心功能分析和实现

     3.1关于加载导航栏的相关代码分析

      @Override
      public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
              Bundle savedInstanceState) {
          return inflater.inflate(R.layout.navigation_bar, container, false);
      }
  
      @Override
      public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
          super.onViewCreated(view, savedInstanceState);
          mNavigationBarView = (NavigationBarView) view;
          final Display display = view.getDisplay();
          // It may not have display when running unit test.
          if (display != null) {
              mDisplayId = display.getDisplayId();
              mIsOnDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
          }
  
          mNavigationBarView.setComponents(mStatusBarLazy.get().getPanelController());
          mNavigationBarView.setDisabledFlags(mDisabledFlags1);
          mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged);
          mNavigationBarView.setOnTouchListener(this::onNavigationTouch);
          if (savedInstanceState != null) {
              mNavigationBarView.getLightTransitionsController().restoreState(savedInstanceState);
          }
          mNavigationBarView.setNavigationIconHints(mNavigationIconHints);
          mNavigationBarView.setWindowVisible(isNavBarWindowVisible());
  
          prepareNavigationBarView();
          checkNavBarModes();
  
          IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
          filter.addAction(Intent.ACTION_SCREEN_ON);
          filter.addAction(Intent.ACTION_USER_SWITCHED);
          mBroadcastDispatcher.registerReceiverWithHandler(mBroadcastReceiver, filter,
                  Handler.getMain(), UserHandle.ALL);
          notifyNavigationBarScreenOn();
  
          mOverviewProxyService.addCallback(mOverviewProxyListener);
          updateSystemUiStateFlags(-1);
  
          // Currently there is no accelerometer sensor on non-default display.
          if (mIsOnDefaultDisplay) {
              final RotationButtonController rotationButtonController =
                      mNavigationBarView.getRotationButtonController();
              rotationButtonController.addRotationCallback(mRotationWatcher);
  
              // Reset user rotation pref to match that of the WindowManager if starting in locked
              // mode. This will automatically happen when switching from auto-rotate to locked mode.
              if (display != null && rotationButtonController.isRotationLocked()) {
                  rotationButtonController.setRotationLockedAtAngle(display.getRotation());
              }
          } else {
              mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
          }
          setDisabled2Flags(mDisabledFlags2);
          if (mIsOnDefaultDisplay) {
              mAssistHandlerViewController =
                  new AssistHandleViewController(mHandler, mNavigationBarView);
              getBarTransitions().addDarkIntensityListener(mAssistHandlerViewController);
          }
  
          initSecondaryHomeHandleForRotation();
      }

  在上述代码中onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
              Bundle savedInstanceState)中加载代码布局代码就是navigation_bar.xml布局文件
而在onViewCreated(View view, @Nullable Bundle savedInstanceState) 中,也是设置mNavigationBarView
的相关参数,所以需要具体看NavigationBarView的相关源码

    private void prepareNavigationBarView() {
         mNavigationBarView.reorient();
 
         ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
         recentsButton.setOnClickListener(this::onRecentsClick);
         recentsButton.setOnTouchListener(this::onRecentsTouch);
         recentsButton.setLongClickable(true);
         recentsButton.setOnLongClickListener(this::onLongPressBackRecents);
 
         ButtonDispatcher backButton = mNavigationBarView.getBackButton();
         backButton.setLongClickable(true);
 
         ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
         homeButton.setOnTouchListener(this::onHomeTouch);
          homeButton.setOnLongClickListener(this::onHomeLongClick);
  
          ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
          accessibilityButton.setOnClickListener(this::onAccessibilityClick);
          accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
          updateAccessibilityServicesState(mAccessibilityManager);
  
          updateScreenPinningGestures();
      }

在NavigationBarFragment.java中的prepareNavigationBarView() 源码中可以看到,backButton recentsButton homeButton 等到导航栏三大键都是调用
NavigationBarView的对应方法的,所以具体的icon设置都是在NavigationBarView中定义的,所以需要看NavigationBarView的相关源码

3.2NavigationBarView的相关源码分析

       public ButtonDispatcher getRecentsButton() {
          return mButtonDispatchers.get(R.id.recent_apps);
      }
  
      public ButtonDispatcher getBackButton() {
          return mButtonDispatchers.get(R.id.back);
      }
  
      public ButtonDispatcher getHomeButton() {
          return mButtonDispatchers.get(R.id.home);
      }

在NavigationBarFragment.java中通过上面三个方法调用导航栏的虚拟按键,然后操作这三个键,来实现对他们的点击事件的处理

      @Override
      public void setLayoutDirection(int layoutDirection) {
          reloadNavIcons();
          super.setLayoutDirection(layoutDirection);
      }
      private void reloadNavIcons() {
          updateIcons(Configuration.EMPTY);
      }

      private void updateIcons(Configuration oldConfig) {
          final boolean orientationChange = oldConfig.orientation != mConfiguration.orientation;
          final boolean densityChange = oldConfig.densityDpi != mConfiguration.densityDpi;
          final boolean dirChange = oldConfig.getLayoutDirection() != mConfiguration.getLayoutDirection();
  
          if (orientationChange || densityChange) {
              mDockedIcon = getDrawable(R.drawable.ic_sysbar_docked);
              mHomeDefaultIcon = getHomeDrawable();
          }
          if (densityChange || dirChange) {
              mRecentIcon = getDrawable(R.drawable.ic_sysbar_recent);
              mContextualButtonGroup.updateIcons();
          }
          if (orientationChange || densityChange || dirChange) {
              mBackIcon = getBackDrawable();
          }
      }

 在NavigationBarView的布局是在setLayoutDirection(int layoutDirection)调用reloadNavIcons(),最终调用updateIcons(Configuration oldConfig) 中来加载导航栏的
从上述代码可以发现,home键的图标是getHomeDrawable()而recents键图标就是getDrawable(R.drawable.ic_sysbar_recent),而back键就是 getBackDrawable()

     public KeyButtonDrawable getBackDrawable() {
          KeyButtonDrawable drawable = getDrawable(getBackDrawableRes());
          orientBackButton(drawable);
          return drawable;
      }
  
      public @DrawableRes int getBackDrawableRes() {
          return chooseNavigationIconDrawableRes(R.drawable.ic_sysbar_back,
                  R.drawable.ic_sysbar_back_quick_step);
      }
  
      public KeyButtonDrawable getHomeDrawable() {
          final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
          KeyButtonDrawable drawable = quickStepEnabled
                  ? getDrawable(R.drawable.ic_sysbar_home_quick_step)
                  : getDrawable(R.drawable.ic_sysbar_home);
          orientHomeButton(drawable);
          return drawable;
      }

通过上述分析,所以back键就是ic_sysbar_back.xml布局,而home键就是ic_sysbar_home布局 recent键就是ic_sysbar_recent布局
接下来看下res/drawable下的icon的xml布局
例如ic_sysbar_back.xml布局如下:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:width="28dp"
     android:height="28dp"
     android:autoMirrored="true"
     android:viewportWidth="28"
     android:viewportHeight="28">
 
     <path
         android:fillColor="?attr/singleToneColor"
         android:pathData="M6.49,14.86c-0.66-0.39-0.66-1.34,0-1.73l6.02-3.53l5.89-3.46C19.11,5.73,20,6.26,20,7.1V14v6.9 c0,0.84-0.89,1.37-1.6,0.95l-5.89-3.46L6.49,14.86z" />
 </vector>

只需要修改width和height属性值就可以了
修改为:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:width="42dp"
     android:height="42dp"
     android:autoMirrored="true"
     android:viewportWidth="42"
     android:viewportHeight="42">
 
     <path
         android:fillColor="?attr/singleToneColor"
         android:pathData="M6.49,14.86c-0.66-0.39-0.66-1.34,0-1.73l6.02-3.53l5.89-3.46C19.11,5.73,20,6.26,20,7.1V14v6.9 c0,0.84-0.89,1.37-1.6,0.95l-5.89-3.46L6.49,14.86z" />
 </vector>

其他的home键和recent键按照这种方式修改就好了 就可以完成功能了

猜你喜欢

转载自blog.csdn.net/baidu_41666295/article/details/127167343
今日推荐