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键按照这种方式修改就好了 就可以完成功能了

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
Android 11 中,状态栏和通知栏的设计有所改变,可能会影响到一些应用程序的通知显示。 如果你想要屏蔽状态栏中的通知,但仍然希望能够收到通知,请尝试以下方法: 1. 检查应用程序通知设置:首先,确保你的应用程序已经开启了通知权限,并且设置了正确的通知渠道。如果应用程序的通知权限被关闭,或者通知渠道被设置为“无声”,那么即使收到了通知,也不会在状态栏中显示。 2. 检查系统设置:在 Android 11 中,系统设置中新增了一个“通知历史记录”选项,用于控制是否在状态栏中显示通知。如果你在系统设置中关闭了“通知历史记录”,那么即使收到了通知,也不会在状态栏中显示。你可以打开系统设置,找到“应用和通知” > “通知历史记录”,然后将其打开即可。 3. 检查第三方应用程序:如果你使用了一些第三方应用程序来管理通知,例如“通知助手”或“通知管理器”,那么可能会导致状态栏中的通知被屏蔽。你可以尝试卸载这些应用程序,或者在应用程序设置中将其权限关闭,然后重新启动手机。 4. 检查系统版本:最后,如果你的手机使用的是 Android 11 的早期版本,可能会存在一些系统缺陷导致通知无法在状态栏中显示。你可以尝试升级到最新的系统版本,或者联系手机制造商寻求技术支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安卓兼职framework应用工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值