当前位置:   article > 正文

2021-10-20 Android 实现动态更换系统底部导航栏图标Icon方案_替换android 12 导航栏的 图标

替换android 12 导航栏的 图标

一、实现思路是接收广播,然后更换图标。

二、修改SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java 里面的代码,调用setImageDrawable函数来更换图标。

  1、添加的代码

  1. diff --git a/vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
  2. old mode 100644
  3. new mode 100755
  4. index 1eab427..c125ab7
  5. --- a/vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
  6. +++ b/vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
  7. @@ -86,6 +86,12 @@ import java.io.FileDescriptor;
  8. import java.io.PrintWriter;
  9. import java.util.function.Consumer;
  10. +import android.content.BroadcastReceiver;
  11. +import android.content.Context;
  12. +import android.content.Intent;
  13. +import android.content.IntentFilter;
  14. +import com.android.systemui.broadcast.BroadcastDispatcher;
  15. +import com.android.systemui.Dependency;
  16. public class NavigationBarView extends FrameLayout implements
  17. NavigationModeController.ModeChangedListener {
  18. final static boolean DEBUG = false;
  19. @@ -154,6 +160,8 @@ public class NavigationBarView extends FrameLayout implements
  20. private FloatingRotationButton mFloatingRotationButton;
  21. private RotationButtonController mRotationButtonController;
  22. + private final BroadcastDispatcher mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
  23. +
  24. /**
  25. * Helper that is responsible for showing the right toast when a disallowed activity operation
  26. * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
  27. @@ -224,6 +232,22 @@ public class NavigationBarView extends FrameLayout implements
  28. true /* showAuxiliarySubtypes */, getContext().getDisplayId());
  29. }
  30. };
  31. + private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  32. + @Override
  33. + public void onReceive(Context context, Intent intent) {
  34. + Log.d(TAG, "BroadcastReceiver mReceiver change icon!!");
  35. + boolean state = intent.getIntExtra("state", 0) != 0;
  36. + if(state){
  37. + getHomeButton().setImageDrawable(mBackIcon);
  38. + getBackButton().setImageDrawable(mHomeDefaultIcon);
  39. + getBackButton().setVisibility(View.VISIBLE);
  40. + getHomeButton().setVisibility(View.VISIBLE);
  41. + }else{
  42. + getHomeButton().setImageDrawable(mHomeDefaultIcon);
  43. + getBackButton().setImageDrawable(mBackIcon);
  44. + }
  45. + }
  46. + };
  47. private final AccessibilityDelegate mQuickStepAccessibilityDelegate =
  48. new AccessibilityDelegate() {
  49. @@ -300,6 +324,10 @@ public class NavigationBarView extends FrameLayout implements
  50. }
  51. mContextualButtonGroup.addButton(accessibilityButton);
  52. + IntentFilter filter = new IntentFilter();
  53. + filter.addAction("android.intent.action.TESTHINT");
  54. + mBroadcastDispatcher.registerReceiver(mReceiver, filter);
  55. +
  56. mOverviewProxyService = Dependency.get(OverviewProxyService.class);
  57. mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
  58. mFloatingRotationButton = new FloatingRotationButton(context);

  2、修改后完整NavigationBarView.java代码

  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.android.systemui.statusbar.phone;
  17. import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
  18. import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
  19. import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
  20. import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
  21. import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
  22. import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
  23. import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SEARCH_DISABLED;
  24. import static com.android.systemui.shared.system.QuickStepContract.isGesturalMode;
  25. import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
  26. import static com.android.systemui.util.Utils.isGesturalModeOnDefaultDisplay;
  27. import android.animation.LayoutTransition;
  28. import android.animation.LayoutTransition.TransitionListener;
  29. import android.animation.ObjectAnimator;
  30. import android.animation.PropertyValuesHolder;
  31. import android.animation.TimeInterpolator;
  32. import android.animation.ValueAnimator;
  33. import android.annotation.DrawableRes;
  34. import android.annotation.Nullable;
  35. import android.app.StatusBarManager;
  36. import android.content.Context;
  37. import android.content.res.Configuration;
  38. import android.graphics.Canvas;
  39. import android.graphics.Point;
  40. import android.graphics.Rect;
  41. import android.graphics.Region;
  42. import android.graphics.Region.Op;
  43. import android.os.Bundle;
  44. import android.util.AttributeSet;
  45. import android.util.Log;
  46. import android.util.SparseArray;
  47. import android.view.Display;
  48. import android.view.MotionEvent;
  49. import android.view.Surface;
  50. import android.view.View;
  51. import android.view.ViewGroup;
  52. import android.view.ViewTreeObserver.InternalInsetsInfo;
  53. import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
  54. import android.view.WindowInsets;
  55. import android.view.WindowManager;
  56. import android.view.accessibility.AccessibilityNodeInfo;
  57. import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
  58. import android.view.inputmethod.InputMethodManager;
  59. import android.widget.FrameLayout;
  60. import com.android.internal.annotations.VisibleForTesting;
  61. import com.android.systemui.Dependency;
  62. import com.android.systemui.Interpolators;
  63. import com.android.systemui.R;
  64. import com.android.systemui.assist.AssistHandleViewController;
  65. import com.android.systemui.model.SysUiState;
  66. import com.android.systemui.recents.OverviewProxyService;
  67. import com.android.systemui.recents.Recents;
  68. import com.android.systemui.recents.RecentsOnboarding;
  69. import com.android.systemui.shared.plugins.PluginManager;
  70. import com.android.systemui.shared.system.ActivityManagerWrapper;
  71. import com.android.systemui.shared.system.QuickStepContract;
  72. import com.android.systemui.shared.system.SysUiStatsLog;
  73. import com.android.systemui.shared.system.WindowManagerWrapper;
  74. import com.android.systemui.stackdivider.Divider;
  75. import com.android.systemui.statusbar.CommandQueue;
  76. import com.android.systemui.statusbar.NavigationBarController;
  77. import com.android.systemui.statusbar.policy.DeadZone;
  78. import com.android.systemui.statusbar.policy.KeyButtonDrawable;
  79. import java.io.FileDescriptor;
  80. import java.io.PrintWriter;
  81. import java.util.function.Consumer;
  82. import android.content.BroadcastReceiver;
  83. import android.content.Context;
  84. import android.content.Intent;
  85. import android.content.IntentFilter;
  86. import com.android.systemui.broadcast.BroadcastDispatcher;
  87. import com.android.systemui.Dependency;
  88. public class NavigationBarView extends FrameLayout implements
  89. NavigationModeController.ModeChangedListener {
  90. final static boolean DEBUG = false;
  91. final static String TAG = "StatusBar/NavBarView";
  92. // slippery nav bar when everything is disabled, e.g. during setup
  93. final static boolean SLIPPERY_WHEN_DISABLED = true;
  94. final static boolean ALTERNATE_CAR_MODE_UI = false;
  95. private final RegionSamplingHelper mRegionSamplingHelper;
  96. private final int mNavColorSampleMargin;
  97. private final SysUiState mSysUiFlagContainer;
  98. private final PluginManager mPluginManager;
  99. View mCurrentView = null;
  100. private View mVertical;
  101. private View mHorizontal;
  102. /** Indicates that navigation bar is vertical. */
  103. private boolean mIsVertical;
  104. private int mCurrentRotation = -1;
  105. boolean mLongClickableAccessibilityButton;
  106. int mDisabledFlags = 0;
  107. int mNavigationIconHints = 0;
  108. private int mNavBarMode;
  109. private Rect mHomeButtonBounds = new Rect();
  110. private Rect mBackButtonBounds = new Rect();
  111. private Rect mRecentsButtonBounds = new Rect();
  112. private Rect mRotationButtonBounds = new Rect();
  113. private final Region mActiveRegion = new Region();
  114. private int[] mTmpPosition = new int[2];
  115. private KeyButtonDrawable mBackIcon;
  116. private KeyButtonDrawable mHomeDefaultIcon;
  117. private KeyButtonDrawable mRecentIcon;
  118. private KeyButtonDrawable mDockedIcon;
  119. private EdgeBackGestureHandler mEdgeBackGestureHandler;
  120. private final DeadZone mDeadZone;
  121. private boolean mDeadZoneConsuming = false;
  122. private final NavigationBarTransitions mBarTransitions;
  123. private final OverviewProxyService mOverviewProxyService;
  124. // performs manual animation in sync with layout transitions
  125. private final NavTransitionListener mTransitionListener = new NavTransitionListener();
  126. private OnVerticalChangedListener mOnVerticalChangedListener;
  127. private boolean mLayoutTransitionsEnabled = true;
  128. private boolean mWakeAndUnlocking;
  129. private boolean mUseCarModeUi = false;
  130. private boolean mInCarMode = false;
  131. private boolean mDockedStackExists;
  132. private boolean mImeVisible;
  133. private boolean mScreenOn = true;
  134. private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
  135. private final ContextualButtonGroup mContextualButtonGroup;
  136. private Configuration mConfiguration;
  137. private Configuration mTmpLastConfiguration;
  138. private NavigationBarInflaterView mNavigationInflaterView;
  139. private RecentsOnboarding mRecentsOnboarding;
  140. private NotificationPanelViewController mPanelView;
  141. private FloatingRotationButton mFloatingRotationButton;
  142. private RotationButtonController mRotationButtonController;
  143. private final BroadcastDispatcher mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
  144. /**
  145. * Helper that is responsible for showing the right toast when a disallowed activity operation
  146. * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
  147. * fully locked mode we only show that unlocking is blocked.
  148. */
  149. private ScreenPinningNotify mScreenPinningNotify;
  150. private Rect mSamplingBounds = new Rect();
  151. /**
  152. * When quickswitching between apps of different orientations, we draw a secondary home handle
  153. * in the position of the first app's orientation. This rect represents the region of that
  154. * home handle so we can apply the correct light/dark luma on that.
  155. * @see {@link NavigationBarFragment#mOrientationHandle}
  156. */
  157. @Nullable
  158. private Rect mOrientedHandleSamplingRegion;
  159. private class NavTransitionListener implements TransitionListener {
  160. private boolean mBackTransitioning;
  161. private boolean mHomeAppearing;
  162. private long mStartDelay;
  163. private long mDuration;
  164. private TimeInterpolator mInterpolator;
  165. @Override
  166. public void startTransition(LayoutTransition transition, ViewGroup container,
  167. View view, int transitionType) {
  168. if (view.getId() == R.id.back) {
  169. mBackTransitioning = true;
  170. } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
  171. mHomeAppearing = true;
  172. mStartDelay = transition.getStartDelay(transitionType);
  173. mDuration = transition.getDuration(transitionType);
  174. mInterpolator = transition.getInterpolator(transitionType);
  175. }
  176. }
  177. @Override
  178. public void endTransition(LayoutTransition transition, ViewGroup container,
  179. View view, int transitionType) {
  180. if (view.getId() == R.id.back) {
  181. mBackTransitioning = false;
  182. } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
  183. mHomeAppearing = false;
  184. }
  185. }
  186. public void onBackAltCleared() {
  187. ButtonDispatcher backButton = getBackButton();
  188. // When dismissing ime during unlock, force the back button to run the same appearance
  189. // animation as home (if we catch this condition early enough).
  190. if (!mBackTransitioning && backButton.getVisibility() == VISIBLE
  191. && mHomeAppearing && getHomeButton().getAlpha() == 0) {
  192. getBackButton().setAlpha(0);
  193. ValueAnimator a = ObjectAnimator.ofFloat(backButton, "alpha", 0, 1);
  194. a.setStartDelay(mStartDelay);
  195. a.setDuration(mDuration);
  196. a.setInterpolator(mInterpolator);
  197. a.start();
  198. }
  199. }
  200. }
  201. private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
  202. @Override
  203. public void onClick(View view) {
  204. mContext.getSystemService(InputMethodManager.class).showInputMethodPickerFromSystem(
  205. true /* showAuxiliarySubtypes */, getContext().getDisplayId());
  206. }
  207. };
  208. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  209. @Override
  210. public void onReceive(Context context, Intent intent) {
  211. Log.d(TAG, "BroadcastReceiver mReceiver change icon!!");
  212. boolean state = intent.getIntExtra("state", 0) != 0;
  213. if(state){
  214. getHomeButton().setImageDrawable(mBackIcon);
  215. getBackButton().setImageDrawable(mHomeDefaultIcon);
  216. getBackButton().setVisibility(View.VISIBLE);
  217. getHomeButton().setVisibility(View.VISIBLE);
  218. }else{
  219. getHomeButton().setImageDrawable(mHomeDefaultIcon);
  220. getBackButton().setImageDrawable(mBackIcon);
  221. }
  222. }
  223. };
  224. private final AccessibilityDelegate mQuickStepAccessibilityDelegate =
  225. new AccessibilityDelegate() {
  226. private AccessibilityAction mToggleOverviewAction;
  227. @Override
  228. public void onInitializeAccessibilityNodeInfo(View host,
  229. AccessibilityNodeInfo info) {
  230. super.onInitializeAccessibilityNodeInfo(host, info);
  231. if (mToggleOverviewAction == null) {
  232. mToggleOverviewAction = new AccessibilityAction(
  233. R.id.action_toggle_overview, getContext().getString(
  234. R.string.quick_step_accessibility_toggle_overview));
  235. }
  236. info.addAction(mToggleOverviewAction);
  237. }
  238. @Override
  239. public boolean performAccessibilityAction(View host, int action, Bundle args) {
  240. if (action == R.id.action_toggle_overview) {
  241. Dependency.get(Recents.class).toggleRecentApps();
  242. } else {
  243. return super.performAccessibilityAction(host, action, args);
  244. }
  245. return true;
  246. }
  247. };
  248. private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener = info -> {
  249. // When the nav bar is in 2-button or 3-button mode, or when IME is visible in fully
  250. // gestural mode, the entire nav bar should be touchable.
  251. if (!mEdgeBackGestureHandler.isHandlingGestures() || mImeVisible) {
  252. info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
  253. return;
  254. }
  255. info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
  256. ButtonDispatcher imeSwitchButton = getImeSwitchButton();
  257. if (imeSwitchButton.getVisibility() == VISIBLE) {
  258. // If the IME is not up, but the ime switch button is visible, then make sure that
  259. // button is touchable
  260. int[] loc = new int[2];
  261. View buttonView = imeSwitchButton.getCurrentView();
  262. buttonView.getLocationInWindow(loc);
  263. info.touchableRegion.set(loc[0], loc[1], loc[0] + buttonView.getWidth(),
  264. loc[1] + buttonView.getHeight());
  265. return;
  266. }
  267. info.touchableRegion.setEmpty();
  268. };
  269. public NavigationBarView(Context context, AttributeSet attrs) {
  270. super(context, attrs);
  271. mIsVertical = false;
  272. mLongClickableAccessibilityButton = false;
  273. mNavBarMode = Dependency.get(NavigationModeController.class).addListener(this);
  274. boolean isGesturalMode = isGesturalMode(mNavBarMode);
  275. mSysUiFlagContainer = Dependency.get(SysUiState.class);
  276. mPluginManager = Dependency.get(PluginManager.class);
  277. // Set up the context group of buttons
  278. mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container);
  279. final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher,
  280. R.drawable.ic_ime_switcher_default);
  281. final RotationContextButton rotateSuggestionButton = new RotationContextButton(
  282. R.id.rotate_suggestion, R.drawable.ic_sysbar_rotate_button);
  283. final ContextualButton accessibilityButton =
  284. new ContextualButton(R.id.accessibility_button,
  285. R.drawable.ic_sysbar_accessibility_button);
  286. mContextualButtonGroup.addButton(imeSwitcherButton);
  287. if (!isGesturalMode) {
  288. mContextualButtonGroup.addButton(rotateSuggestionButton);
  289. }
  290. mContextualButtonGroup.addButton(accessibilityButton);
  291. IntentFilter filter = new IntentFilter();
  292. filter.addAction("android.intent.action.TESTHINT");
  293. mBroadcastDispatcher.registerReceiver(mReceiver, filter);
  294. mOverviewProxyService = Dependency.get(OverviewProxyService.class);
  295. mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
  296. mFloatingRotationButton = new FloatingRotationButton(context);
  297. mRotationButtonController = new RotationButtonController(context,
  298. R.style.RotateButtonCCWStart90,
  299. isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton);
  300. mConfiguration = new Configuration();
  301. mTmpLastConfiguration = new Configuration();
  302. mConfiguration.updateFrom(context.getResources().getConfiguration());
  303. mScreenPinningNotify = new ScreenPinningNotify(mContext);
  304. mBarTransitions = new NavigationBarTransitions(this, Dependency.get(CommandQueue.class));
  305. mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
  306. mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
  307. mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
  308. mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
  309. mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
  310. mButtonDispatchers.put(R.id.accessibility_button, accessibilityButton);
  311. mButtonDispatchers.put(R.id.rotate_suggestion, rotateSuggestionButton);
  312. mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
  313. mDeadZone = new DeadZone(this);
  314. mNavColorSampleMargin = getResources()
  315. .getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
  316. mEdgeBackGestureHandler = new EdgeBackGestureHandler(context, mOverviewProxyService,
  317. mSysUiFlagContainer, mPluginManager, this::updateStates);
  318. mRegionSamplingHelper = new RegionSamplingHelper(this,
  319. new RegionSamplingHelper.SamplingCallback() {
  320. @Override
  321. public void onRegionDarknessChanged(boolean isRegionDark) {
  322. getLightTransitionsController().setIconsDark(!isRegionDark ,
  323. true /* animate */);
  324. }
  325. @Override
  326. public Rect getSampledRegion(View sampledView) {
  327. if (mOrientedHandleSamplingRegion != null) {
  328. return mOrientedHandleSamplingRegion;
  329. }
  330. updateSamplingRect();
  331. return mSamplingBounds;
  332. }
  333. @Override
  334. public boolean isSamplingEnabled() {
  335. return isGesturalModeOnDefaultDisplay(getContext(), mNavBarMode);
  336. }
  337. });
  338. }
  339. public NavigationBarTransitions getBarTransitions() {
  340. return mBarTransitions;
  341. }
  342. public LightBarTransitionsController getLightTransitionsController() {
  343. return mBarTransitions.getLightTransitionsController();
  344. }
  345. public void setComponents(NotificationPanelViewController panel) {
  346. mPanelView = panel;
  347. updatePanelSystemUiStateFlags();
  348. }
  349. public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
  350. mOnVerticalChangedListener = onVerticalChangedListener;
  351. notifyVerticalChangedListener(mIsVertical);
  352. }
  353. @Override
  354. public boolean onInterceptTouchEvent(MotionEvent event) {
  355. if (isGesturalMode(mNavBarMode) && mImeVisible
  356. && event.getAction() == MotionEvent.ACTION_DOWN) {
  357. SysUiStatsLog.write(SysUiStatsLog.IME_TOUCH_REPORTED,
  358. (int) event.getX(), (int) event.getY());
  359. }
  360. return shouldDeadZoneConsumeTouchEvents(event) || super.onInterceptTouchEvent(event);
  361. }
  362. @Override
  363. public boolean onTouchEvent(MotionEvent event) {
  364. shouldDeadZoneConsumeTouchEvents(event);
  365. return super.onTouchEvent(event);
  366. }
  367. void onTransientStateChanged(boolean isTransient) {
  368. mEdgeBackGestureHandler.onNavBarTransientStateChanged(isTransient);
  369. }
  370. void onBarTransition(int newMode) {
  371. if (newMode == MODE_OPAQUE) {
  372. // If the nav bar background is opaque, stop auto tinting since we know the icons are
  373. // showing over a dark background
  374. mRegionSamplingHelper.stop();
  375. getLightTransitionsController().setIconsDark(false /* dark */, true /* animate */);
  376. } else {
  377. mRegionSamplingHelper.start(mSamplingBounds);
  378. }
  379. }
  380. private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) {
  381. int action = event.getActionMasked();
  382. if (action == MotionEvent.ACTION_DOWN) {
  383. mDeadZoneConsuming = false;
  384. }
  385. if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) {
  386. switch (action) {
  387. case MotionEvent.ACTION_DOWN:
  388. // Allow gestures starting in the deadzone to be slippery
  389. setSlippery(true);
  390. mDeadZoneConsuming = true;
  391. break;
  392. case MotionEvent.ACTION_CANCEL:
  393. case MotionEvent.ACTION_UP:
  394. // When a gesture started in the deadzone is finished, restore slippery state
  395. updateSlippery();
  396. mDeadZoneConsuming = false;
  397. break;
  398. }
  399. return true;
  400. }
  401. return false;
  402. }
  403. public void abortCurrentGesture() {
  404. getHomeButton().abortCurrentGesture();
  405. }
  406. public View getCurrentView() {
  407. return mCurrentView;
  408. }
  409. public RotationButtonController getRotationButtonController() {
  410. return mRotationButtonController;
  411. }
  412. public FloatingRotationButton getFloatingRotationButton() {
  413. return mFloatingRotationButton;
  414. }
  415. public ButtonDispatcher getRecentsButton() {
  416. return mButtonDispatchers.get(R.id.recent_apps);
  417. }
  418. public ButtonDispatcher getBackButton() {
  419. return mButtonDispatchers.get(R.id.back);
  420. }
  421. public ButtonDispatcher getHomeButton() {
  422. return mButtonDispatchers.get(R.id.home);
  423. }
  424. public ButtonDispatcher getImeSwitchButton() {
  425. return mButtonDispatchers.get(R.id.ime_switcher);
  426. }
  427. public ButtonDispatcher getAccessibilityButton() {
  428. return mButtonDispatchers.get(R.id.accessibility_button);
  429. }
  430. public RotationContextButton getRotateSuggestionButton() {
  431. return (RotationContextButton) mButtonDispatchers.get(R.id.rotate_suggestion);
  432. }
  433. public ButtonDispatcher getHomeHandle() {
  434. return mButtonDispatchers.get(R.id.home_handle);
  435. }
  436. public SparseArray<ButtonDispatcher> getButtonDispatchers() {
  437. return mButtonDispatchers;
  438. }
  439. public boolean isRecentsButtonVisible() {
  440. return getRecentsButton().getVisibility() == View.VISIBLE;
  441. }
  442. public boolean isOverviewEnabled() {
  443. return (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) == 0;
  444. }
  445. public boolean isQuickStepSwipeUpEnabled() {
  446. return mOverviewProxyService.shouldShowSwipeUpUI() && isOverviewEnabled();
  447. }
  448. private void reloadNavIcons() {
  449. updateIcons(Configuration.EMPTY);
  450. }
  451. private void updateIcons(Configuration oldConfig) {
  452. final boolean orientationChange = oldConfig.orientation != mConfiguration.orientation;
  453. final boolean densityChange = oldConfig.densityDpi != mConfiguration.densityDpi;
  454. final boolean dirChange = oldConfig.getLayoutDirection() != mConfiguration.getLayoutDirection();
  455. if (orientationChange || densityChange) {
  456. mDockedIcon = getDrawable(R.drawable.ic_sysbar_docked);
  457. mHomeDefaultIcon = getHomeDrawable();
  458. }
  459. if (densityChange || dirChange) {
  460. mRecentIcon = getDrawable(R.drawable.ic_sysbar_recent);
  461. mContextualButtonGroup.updateIcons();
  462. }
  463. if (orientationChange || densityChange || dirChange) {
  464. mBackIcon = getBackDrawable();
  465. }
  466. }
  467. public KeyButtonDrawable getBackDrawable() {
  468. KeyButtonDrawable drawable = getDrawable(getBackDrawableRes());
  469. orientBackButton(drawable);
  470. return drawable;
  471. }
  472. public @DrawableRes int getBackDrawableRes() {
  473. return chooseNavigationIconDrawableRes(R.drawable.ic_sysbar_back,
  474. R.drawable.ic_sysbar_back_quick_step);
  475. }
  476. public KeyButtonDrawable getHomeDrawable() {
  477. final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
  478. KeyButtonDrawable drawable = quickStepEnabled
  479. ? getDrawable(R.drawable.ic_sysbar_home_quick_step)
  480. : getDrawable(R.drawable.ic_sysbar_home);
  481. orientHomeButton(drawable);
  482. return drawable;
  483. }
  484. private void orientBackButton(KeyButtonDrawable drawable) {
  485. final boolean useAltBack =
  486. (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
  487. final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
  488. float degrees = useAltBack ? (isRtl ? 90 : -90) : 0;
  489. if (drawable.getRotation() == degrees) {
  490. return;
  491. }
  492. if (isGesturalMode(mNavBarMode)) {
  493. drawable.setRotation(degrees);
  494. return;
  495. }
  496. // Animate the back button's rotation to the new degrees and only in portrait move up the
  497. // back button to line up with the other buttons
  498. float targetY = !mOverviewProxyService.shouldShowSwipeUpUI() && !mIsVertical && useAltBack
  499. ? - getResources().getDimension(R.dimen.navbar_back_button_ime_offset)
  500. : 0;
  501. ObjectAnimator navBarAnimator = ObjectAnimator.ofPropertyValuesHolder(drawable,
  502. PropertyValuesHolder.ofFloat(KeyButtonDrawable.KEY_DRAWABLE_ROTATE, degrees),
  503. PropertyValuesHolder.ofFloat(KeyButtonDrawable.KEY_DRAWABLE_TRANSLATE_Y, targetY));
  504. navBarAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
  505. navBarAnimator.setDuration(200);
  506. navBarAnimator.start();
  507. }
  508. private void orientHomeButton(KeyButtonDrawable drawable) {
  509. drawable.setRotation(mIsVertical ? 90 : 0);
  510. }
  511. private KeyButtonDrawable chooseNavigationIconDrawable(@DrawableRes int icon,
  512. @DrawableRes int quickStepIcon) {
  513. return getDrawable(chooseNavigationIconDrawableRes(icon, quickStepIcon));
  514. }
  515. private @DrawableRes int chooseNavigationIconDrawableRes(@DrawableRes int icon,
  516. @DrawableRes int quickStepIcon) {
  517. final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
  518. return quickStepEnabled ? quickStepIcon : icon;
  519. }
  520. private KeyButtonDrawable getDrawable(@DrawableRes int icon) {
  521. return KeyButtonDrawable.create(mContext, icon, true /* hasShadow */);
  522. }
  523. private KeyButtonDrawable getDrawable(@DrawableRes int icon, boolean hasShadow) {
  524. return KeyButtonDrawable.create(mContext, icon, hasShadow);
  525. }
  526. /** To be called when screen lock/unlock state changes */
  527. public void onScreenStateChanged(boolean isScreenOn) {
  528. mScreenOn = isScreenOn;
  529. if (isScreenOn) {
  530. if (isGesturalModeOnDefaultDisplay(getContext(), mNavBarMode)) {
  531. mRegionSamplingHelper.start(mSamplingBounds);
  532. }
  533. } else {
  534. mRegionSamplingHelper.stop();
  535. }
  536. }
  537. public void setWindowVisible(boolean visible) {
  538. mRegionSamplingHelper.setWindowVisible(visible);
  539. mRotationButtonController.onNavigationBarWindowVisibilityChange(visible);
  540. }
  541. @Override
  542. public void setLayoutDirection(int layoutDirection) {
  543. reloadNavIcons();
  544. super.setLayoutDirection(layoutDirection);
  545. }
  546. public void setNavigationIconHints(int hints) {
  547. if (hints == mNavigationIconHints) return;
  548. final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
  549. final boolean oldBackAlt =
  550. (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
  551. if (newBackAlt != oldBackAlt) {
  552. onImeVisibilityChanged(newBackAlt);
  553. }
  554. if (DEBUG) {
  555. android.widget.Toast.makeText(getContext(),
  556. "Navigation icon hints = " + hints,
  557. 500).show();
  558. }
  559. mNavigationIconHints = hints;
  560. updateNavButtonIcons();
  561. }
  562. private void onImeVisibilityChanged(boolean visible) {
  563. if (!visible) {
  564. mTransitionListener.onBackAltCleared();
  565. }
  566. mImeVisible = visible;
  567. mRotationButtonController.getRotationButton().setCanShowRotationButton(!mImeVisible);
  568. }
  569. public void setDisabledFlags(int disabledFlags) {
  570. if (mDisabledFlags == disabledFlags) return;
  571. final boolean overviewEnabledBefore = isOverviewEnabled();
  572. mDisabledFlags = disabledFlags;
  573. // Update icons if overview was just enabled to ensure the correct icons are present
  574. if (!overviewEnabledBefore && isOverviewEnabled()) {
  575. reloadNavIcons();
  576. }
  577. updateNavButtonIcons();
  578. updateSlippery();
  579. setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
  580. updateDisabledSystemUiStateFlags();
  581. }
  582. public void updateNavButtonIcons() {
  583. // We have to replace or restore the back and home button icons when exiting or entering
  584. // carmode, respectively. Recents are not available in CarMode in nav bar so change
  585. // to recent icon is not required.
  586. final boolean useAltBack =
  587. (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
  588. KeyButtonDrawable backIcon = mBackIcon;
  589. orientBackButton(backIcon);
  590. KeyButtonDrawable homeIcon = mHomeDefaultIcon;
  591. if (!mUseCarModeUi) {
  592. orientHomeButton(homeIcon);
  593. }
  594. getHomeButton().setImageDrawable(homeIcon);
  595. getBackButton().setImageDrawable(backIcon);
  596. updateRecentsIcon();
  597. // Update IME button visibility, a11y and rotate button always overrides the appearance
  598. mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher,
  599. (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
  600. mBarTransitions.reapplyDarkIntensity();
  601. boolean disableHome = isGesturalMode(mNavBarMode)
  602. || ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
  603. // Always disable recents when alternate car mode UI is active and for secondary displays.
  604. boolean disableRecent = isRecentsButtonDisabled();
  605. // Disable the home handle if both hone and recents are disabled
  606. boolean disableHomeHandle = disableRecent
  607. && ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
  608. boolean disableBack = !useAltBack && (mEdgeBackGestureHandler.isHandlingGestures()
  609. || ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0));
  610. // When screen pinning, don't hide back and home when connected service or back and
  611. // recents buttons when disconnected from launcher service in screen pinning mode,
  612. // as they are used for exiting.
  613. final boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
  614. if (mOverviewProxyService.isEnabled()) {
  615. // Force disable recents when not in legacy mode
  616. disableRecent |= !QuickStepContract.isLegacyMode(mNavBarMode);
  617. if (pinningActive && !QuickStepContract.isGesturalMode(mNavBarMode)) {
  618. disableBack = disableHome = false;
  619. }
  620. } else if (pinningActive) {
  621. disableBack = disableRecent = false;
  622. }
  623. ViewGroup navButtons = getCurrentView().findViewById(R.id.nav_buttons);
  624. if (navButtons != null) {
  625. LayoutTransition lt = navButtons.getLayoutTransition();
  626. if (lt != null) {
  627. if (!lt.getTransitionListeners().contains(mTransitionListener)) {
  628. lt.addTransitionListener(mTransitionListener);
  629. }
  630. }
  631. }
  632. getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
  633. getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
  634. getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
  635. getHomeHandle().setVisibility(disableHomeHandle ? View.INVISIBLE : View.VISIBLE);
  636. }
  637. @VisibleForTesting
  638. boolean isRecentsButtonDisabled() {
  639. return mUseCarModeUi || !isOverviewEnabled()
  640. || getContext().getDisplayId() != Display.DEFAULT_DISPLAY;
  641. }
  642. private Display getContextDisplay() {
  643. return getContext().getDisplay();
  644. }
  645. public void setLayoutTransitionsEnabled(boolean enabled) {
  646. mLayoutTransitionsEnabled = enabled;
  647. updateLayoutTransitionsEnabled();
  648. }
  649. public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
  650. setUseFadingAnimations(wakeAndUnlocking);
  651. mWakeAndUnlocking = wakeAndUnlocking;
  652. updateLayoutTransitionsEnabled();
  653. }
  654. private void updateLayoutTransitionsEnabled() {
  655. boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
  656. ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
  657. LayoutTransition lt = navButtons.getLayoutTransition();
  658. if (lt != null) {
  659. if (enabled) {
  660. lt.enableTransitionType(LayoutTransition.APPEARING);
  661. lt.enableTransitionType(LayoutTransition.DISAPPEARING);
  662. lt.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
  663. lt.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
  664. } else {
  665. lt.disableTransitionType(LayoutTransition.APPEARING);
  666. lt.disableTransitionType(LayoutTransition.DISAPPEARING);
  667. lt.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
  668. lt.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
  669. }
  670. }
  671. }
  672. private void setUseFadingAnimations(boolean useFadingAnimations) {
  673. WindowManager.LayoutParams lp = (WindowManager.LayoutParams) ((ViewGroup) getParent())
  674. .getLayoutParams();
  675. if (lp != null) {
  676. boolean old = lp.windowAnimations != 0;
  677. if (!old && useFadingAnimations) {
  678. lp.windowAnimations = R.style.Animation_NavigationBarFadeIn;
  679. } else if (old && !useFadingAnimations) {
  680. lp.windowAnimations = 0;
  681. } else {
  682. return;
  683. }
  684. WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
  685. wm.updateViewLayout((View) getParent(), lp);
  686. }
  687. }
  688. public void onStatusBarPanelStateChanged() {
  689. updateSlippery();
  690. updatePanelSystemUiStateFlags();
  691. }
  692. public void updateDisabledSystemUiStateFlags() {
  693. int displayId = mContext.getDisplayId();
  694. mSysUiFlagContainer.setFlag(SYSUI_STATE_SCREEN_PINNING,
  695. ActivityManagerWrapper.getInstance().isScreenPinningActive())
  696. .setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
  697. (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0)
  698. .setFlag(SYSUI_STATE_HOME_DISABLED,
  699. (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0)
  700. .setFlag(SYSUI_STATE_SEARCH_DISABLED,
  701. (mDisabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0)
  702. .commitUpdate(displayId);
  703. }
  704. public void updatePanelSystemUiStateFlags() {
  705. int displayId = mContext.getDisplayId();
  706. if (SysUiState.DEBUG) {
  707. Log.d(TAG, "Updating panel sysui state flags: panelView=" + mPanelView);
  708. }
  709. if (mPanelView != null) {
  710. if (SysUiState.DEBUG) {
  711. Log.d(TAG, "Updating panel sysui state flags: fullyExpanded="
  712. + mPanelView.isFullyExpanded() + " inQs=" + mPanelView.isInSettings());
  713. }
  714. mSysUiFlagContainer.setFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
  715. mPanelView.isFullyExpanded() && !mPanelView.isInSettings())
  716. .setFlag(SYSUI_STATE_QUICK_SETTINGS_EXPANDED,
  717. mPanelView.isInSettings())
  718. .commitUpdate(displayId);
  719. }
  720. }
  721. public void updateStates() {
  722. final boolean showSwipeUpUI = mOverviewProxyService.shouldShowSwipeUpUI();
  723. if (mNavigationInflaterView != null) {
  724. // Reinflate the navbar if needed, no-op unless the swipe up state changes
  725. mNavigationInflaterView.onLikelyDefaultLayoutChange();
  726. }
  727. updateSlippery();
  728. reloadNavIcons();
  729. updateNavButtonIcons();
  730. setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
  731. WindowManagerWrapper.getInstance().setNavBarVirtualKeyHapticFeedbackEnabled(!showSwipeUpUI);
  732. getHomeButton().setAccessibilityDelegate(
  733. showSwipeUpUI ? mQuickStepAccessibilityDelegate : null);
  734. }
  735. /**
  736. * Updates the {@link WindowManager.LayoutParams.FLAG_SLIPPERY} state dependent on if swipe up
  737. * is enabled, or the notifications is fully opened without being in an animated state. If
  738. * slippery is enabled, touch events will leave the nav bar window and enter into the fullscreen
  739. * app/home window, if not nav bar will receive a cancelled touch event once gesture leaves bar.
  740. */
  741. public void updateSlippery() {
  742. setSlippery(!isQuickStepSwipeUpEnabled() ||
  743. (mPanelView != null && mPanelView.isFullyExpanded() && !mPanelView.isCollapsing()));
  744. }
  745. private void setSlippery(boolean slippery) {
  746. setWindowFlag(WindowManager.LayoutParams.FLAG_SLIPPERY, slippery);
  747. }
  748. private void setWindowFlag(int flags, boolean enable) {
  749. final ViewGroup navbarView = ((ViewGroup) getParent());
  750. if (navbarView == null) {
  751. return;
  752. }
  753. WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView.getLayoutParams();
  754. if (lp == null || enable == ((lp.flags & flags) != 0)) {
  755. return;
  756. }
  757. if (enable) {
  758. lp.flags |= flags;
  759. } else {
  760. lp.flags &= ~flags;
  761. }
  762. WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
  763. wm.updateViewLayout(navbarView, lp);
  764. }
  765. @Override
  766. public void onNavigationModeChanged(int mode) {
  767. mNavBarMode = mode;
  768. mBarTransitions.onNavigationModeChanged(mNavBarMode);
  769. mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode);
  770. mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
  771. getRotateSuggestionButton().onNavigationModeChanged(mNavBarMode);
  772. if (isGesturalMode(mNavBarMode)) {
  773. mRegionSamplingHelper.start(mSamplingBounds);
  774. } else {
  775. mRegionSamplingHelper.stop();
  776. }
  777. }
  778. public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
  779. mLongClickableAccessibilityButton = longClickable;
  780. getAccessibilityButton().setLongClickable(longClickable);
  781. mContextualButtonGroup.setButtonVisibility(R.id.accessibility_button, visible);
  782. }
  783. void hideRecentsOnboarding() {
  784. mRecentsOnboarding.hide(true);
  785. }
  786. @Override
  787. public void onFinishInflate() {
  788. super.onFinishInflate();
  789. mNavigationInflaterView = findViewById(R.id.navigation_inflater);
  790. mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
  791. getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
  792. Divider divider = Dependency.get(Divider.class);
  793. divider.registerInSplitScreenListener(mDockedListener);
  794. updateOrientationViews();
  795. reloadNavIcons();
  796. }
  797. @Override
  798. protected void onDraw(Canvas canvas) {
  799. mDeadZone.onDraw(canvas);
  800. super.onDraw(canvas);
  801. }
  802. private void updateSamplingRect() {
  803. mSamplingBounds.setEmpty();
  804. // TODO: Extend this to 2/3 button layout as well
  805. View view = getHomeHandle().getCurrentView();
  806. if (view != null) {
  807. int[] pos = new int[2];
  808. view.getLocationOnScreen(pos);
  809. Point displaySize = new Point();
  810. view.getContext().getDisplay().getRealSize(displaySize);
  811. final Rect samplingBounds = new Rect(pos[0] - mNavColorSampleMargin,
  812. displaySize.y - getNavBarHeight(),
  813. pos[0] + view.getWidth() + mNavColorSampleMargin,
  814. displaySize.y);
  815. mSamplingBounds.set(samplingBounds);
  816. }
  817. }
  818. void setOrientedHandleSamplingRegion(Rect orientedHandleSamplingRegion) {
  819. mOrientedHandleSamplingRegion = orientedHandleSamplingRegion;
  820. mRegionSamplingHelper.updateSamplingRect();
  821. }
  822. @Override
  823. protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  824. super.onLayout(changed, left, top, right, bottom);
  825. mActiveRegion.setEmpty();
  826. updateButtonLocation(getBackButton(), mBackButtonBounds, true);
  827. updateButtonLocation(getHomeButton(), mHomeButtonBounds, false);
  828. updateButtonLocation(getRecentsButton(), mRecentsButtonBounds, false);
  829. updateButtonLocation(getRotateSuggestionButton(), mRotationButtonBounds, true);
  830. // TODO: Handle button visibility changes
  831. mOverviewProxyService.onActiveNavBarRegionChanges(mActiveRegion);
  832. mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
  833. }
  834. private void updateButtonLocation(ButtonDispatcher button, Rect buttonBounds,
  835. boolean isActive) {
  836. View view = button.getCurrentView();
  837. if (view == null) {
  838. buttonBounds.setEmpty();
  839. return;
  840. }
  841. // Temporarily reset the translation back to origin to get the position in window
  842. final float posX = view.getTranslationX();
  843. final float posY = view.getTranslationY();
  844. view.setTranslationX(0);
  845. view.setTranslationY(0);
  846. if (isActive) {
  847. view.getLocationOnScreen(mTmpPosition);
  848. buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
  849. mTmpPosition[0] + view.getMeasuredWidth(),
  850. mTmpPosition[1] + view.getMeasuredHeight());
  851. mActiveRegion.op(buttonBounds, Op.UNION);
  852. }
  853. view.getLocationInWindow(mTmpPosition);
  854. buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
  855. mTmpPosition[0] + view.getMeasuredWidth(),
  856. mTmpPosition[1] + view.getMeasuredHeight());
  857. view.setTranslationX(posX);
  858. view.setTranslationY(posY);
  859. }
  860. private void updateOrientationViews() {
  861. mHorizontal = findViewById(R.id.horizontal);
  862. mVertical = findViewById(R.id.vertical);
  863. updateCurrentView();
  864. }
  865. boolean needsReorient(int rotation) {
  866. return mCurrentRotation != rotation;
  867. }
  868. private void updateCurrentView() {
  869. resetViews();
  870. mCurrentView = mIsVertical ? mVertical : mHorizontal;
  871. mCurrentView.setVisibility(View.VISIBLE);
  872. mNavigationInflaterView.setVertical(mIsVertical);
  873. mCurrentRotation = getContextDisplay().getRotation();
  874. mNavigationInflaterView.setAlternativeOrder(mCurrentRotation == Surface.ROTATION_90);
  875. mNavigationInflaterView.updateButtonDispatchersCurrentView();
  876. updateLayoutTransitionsEnabled();
  877. }
  878. private void resetViews() {
  879. mHorizontal.setVisibility(View.GONE);
  880. mVertical.setVisibility(View.GONE);
  881. }
  882. private void updateRecentsIcon() {
  883. mDockedIcon.setRotation(mDockedStackExists && mIsVertical ? 90 : 0);
  884. getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
  885. mBarTransitions.reapplyDarkIntensity();
  886. }
  887. public void showPinningEnterExitToast(boolean entering) {
  888. if (entering) {
  889. mScreenPinningNotify.showPinningStartToast();
  890. } else {
  891. mScreenPinningNotify.showPinningExitToast();
  892. }
  893. }
  894. public void showPinningEscapeToast() {
  895. mScreenPinningNotify.showEscapeToast(
  896. mNavBarMode == NAV_BAR_MODE_GESTURAL, isRecentsButtonVisible());
  897. }
  898. public boolean isVertical() {
  899. return mIsVertical;
  900. }
  901. public void reorient() {
  902. updateCurrentView();
  903. ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
  904. mDeadZone.onConfigurationChanged(mCurrentRotation);
  905. // force the low profile & disabled states into compliance
  906. mBarTransitions.init();
  907. if (DEBUG) {
  908. Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
  909. }
  910. // Resolve layout direction if not resolved since components changing layout direction such
  911. // as changing languages will recreate this view and the direction will be resolved later
  912. if (!isLayoutDirectionResolved()) {
  913. resolveLayoutDirection();
  914. }
  915. updateNavButtonIcons();
  916. getHomeButton().setVertical(mIsVertical);
  917. }
  918. @Override
  919. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  920. int w = MeasureSpec.getSize(widthMeasureSpec);
  921. int h = MeasureSpec.getSize(heightMeasureSpec);
  922. if (DEBUG) Log.d(TAG, String.format(
  923. "onMeasure: (%dx%d) old: (%dx%d)", w, h, getMeasuredWidth(), getMeasuredHeight()));
  924. final boolean newVertical = w > 0 && h > w
  925. && !isGesturalMode(mNavBarMode);
  926. if (newVertical != mIsVertical) {
  927. mIsVertical = newVertical;
  928. if (DEBUG) {
  929. Log.d(TAG, String.format("onMeasure: h=%d, w=%d, vert=%s", h, w,
  930. mIsVertical ? "y" : "n"));
  931. }
  932. reorient();
  933. notifyVerticalChangedListener(newVertical);
  934. }
  935. if (isGesturalMode(mNavBarMode)) {
  936. // Update the nav bar background to match the height of the visible nav bar
  937. int height = mIsVertical
  938. ? getResources().getDimensionPixelSize(
  939. com.android.internal.R.dimen.navigation_bar_height_landscape)
  940. : getResources().getDimensionPixelSize(
  941. com.android.internal.R.dimen.navigation_bar_height);
  942. int frameHeight = getResources().getDimensionPixelSize(
  943. com.android.internal.R.dimen.navigation_bar_frame_height);
  944. mBarTransitions.setBackgroundFrame(new Rect(0, frameHeight - height, w, h));
  945. }
  946. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  947. }
  948. private int getNavBarHeight() {
  949. return mIsVertical
  950. ? getResources().getDimensionPixelSize(
  951. com.android.internal.R.dimen.navigation_bar_height_landscape)
  952. : getResources().getDimensionPixelSize(
  953. com.android.internal.R.dimen.navigation_bar_height);
  954. }
  955. private void notifyVerticalChangedListener(boolean newVertical) {
  956. if (mOnVerticalChangedListener != null) {
  957. mOnVerticalChangedListener.onVerticalChanged(newVertical);
  958. }
  959. }
  960. @Override
  961. protected void onConfigurationChanged(Configuration newConfig) {
  962. super.onConfigurationChanged(newConfig);
  963. mTmpLastConfiguration.updateFrom(mConfiguration);
  964. mConfiguration.updateFrom(newConfig);
  965. boolean uiCarModeChanged = updateCarMode();
  966. updateIcons(mTmpLastConfiguration);
  967. updateRecentsIcon();
  968. mRecentsOnboarding.onConfigurationChanged(mConfiguration);
  969. if (uiCarModeChanged || mTmpLastConfiguration.densityDpi != mConfiguration.densityDpi
  970. || mTmpLastConfiguration.getLayoutDirection() != mConfiguration.getLayoutDirection()) {
  971. // If car mode or density changes, we need to reset the icons.
  972. updateNavButtonIcons();
  973. }
  974. }
  975. /**
  976. * If the configuration changed, update the carmode and return that it was updated.
  977. */
  978. private boolean updateCarMode() {
  979. boolean uiCarModeChanged = false;
  980. if (mConfiguration != null) {
  981. int uiMode = mConfiguration.uiMode & Configuration.UI_MODE_TYPE_MASK;
  982. final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
  983. if (isCarMode != mInCarMode) {
  984. mInCarMode = isCarMode;
  985. if (ALTERNATE_CAR_MODE_UI) {
  986. mUseCarModeUi = isCarMode;
  987. uiCarModeChanged = true;
  988. } else {
  989. // Don't use car mode behavior if ALTERNATE_CAR_MODE_UI not set.
  990. mUseCarModeUi = false;
  991. }
  992. }
  993. }
  994. return uiCarModeChanged;
  995. }
  996. private String getResourceName(int resId) {
  997. if (resId != 0) {
  998. final android.content.res.Resources res = getContext().getResources();
  999. try {
  1000. return res.getResourceName(resId);
  1001. } catch (android.content.res.Resources.NotFoundException ex) {
  1002. return "(unknown)";
  1003. }
  1004. } else {
  1005. return "(null)";
  1006. }
  1007. }
  1008. private static String visibilityToString(int vis) {
  1009. switch (vis) {
  1010. case View.INVISIBLE:
  1011. return "INVISIBLE";
  1012. case View.GONE:
  1013. return "GONE";
  1014. default:
  1015. return "VISIBLE";
  1016. }
  1017. }
  1018. @Override
  1019. protected void onAttachedToWindow() {
  1020. super.onAttachedToWindow();
  1021. requestApplyInsets();
  1022. reorient();
  1023. onNavigationModeChanged(mNavBarMode);
  1024. setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
  1025. if (mRotationButtonController != null) {
  1026. mRotationButtonController.registerListeners();
  1027. }
  1028. mEdgeBackGestureHandler.onNavBarAttached();
  1029. getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
  1030. }
  1031. @Override
  1032. protected void onDetachedFromWindow() {
  1033. super.onDetachedFromWindow();
  1034. Dependency.get(NavigationModeController.class).removeListener(this);
  1035. setUpSwipeUpOnboarding(false);
  1036. for (int i = 0; i < mButtonDispatchers.size(); ++i) {
  1037. mButtonDispatchers.valueAt(i).onDestroy();
  1038. }
  1039. if (mRotationButtonController != null) {
  1040. mRotationButtonController.unregisterListeners();
  1041. }
  1042. mEdgeBackGestureHandler.onNavBarDetached();
  1043. getViewTreeObserver().removeOnComputeInternalInsetsListener(
  1044. mOnComputeInternalInsetsListener);
  1045. }
  1046. private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
  1047. if (connectedToOverviewProxy) {
  1048. mRecentsOnboarding.onConnectedToLauncher();
  1049. } else {
  1050. mRecentsOnboarding.onDisconnectedFromLauncher();
  1051. }
  1052. }
  1053. public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
  1054. pw.println("NavigationBarView {");
  1055. final Rect r = new Rect();
  1056. final Point size = new Point();
  1057. getContextDisplay().getRealSize(size);
  1058. pw.println(String.format(" this: " + StatusBar.viewInfo(this)
  1059. + " " + visibilityToString(getVisibility())));
  1060. getWindowVisibleDisplayFrame(r);
  1061. final boolean offscreen = r.right > size.x || r.bottom > size.y;
  1062. pw.println(" window: "
  1063. + r.toShortString()
  1064. + " " + visibilityToString(getWindowVisibility())
  1065. + (offscreen ? " OFFSCREEN!" : ""));
  1066. pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s %f",
  1067. getResourceName(getCurrentView().getId()),
  1068. getCurrentView().getWidth(), getCurrentView().getHeight(),
  1069. visibilityToString(getCurrentView().getVisibility()),
  1070. getCurrentView().getAlpha()));
  1071. pw.println(String.format(" disabled=0x%08x vertical=%s darkIntensity=%.2f",
  1072. mDisabledFlags,
  1073. mIsVertical ? "true" : "false",
  1074. getLightTransitionsController().getCurrentDarkIntensity()));
  1075. pw.println(" mOrientedHandleSamplingRegion: " + mOrientedHandleSamplingRegion);
  1076. dumpButton(pw, "back", getBackButton());
  1077. dumpButton(pw, "home", getHomeButton());
  1078. dumpButton(pw, "rcnt", getRecentsButton());
  1079. dumpButton(pw, "rota", getRotateSuggestionButton());
  1080. dumpButton(pw, "a11y", getAccessibilityButton());
  1081. pw.println(" }");
  1082. pw.println(" mScreenOn: " + mScreenOn);
  1083. if (mNavigationInflaterView != null) {
  1084. mNavigationInflaterView.dump(pw);
  1085. }
  1086. mContextualButtonGroup.dump(pw);
  1087. mRecentsOnboarding.dump(pw);
  1088. mRegionSamplingHelper.dump(pw);
  1089. mEdgeBackGestureHandler.dump(pw);
  1090. }
  1091. @Override
  1092. public WindowInsets onApplyWindowInsets(WindowInsets insets) {
  1093. int leftInset = insets.getSystemWindowInsetLeft();
  1094. int rightInset = insets.getSystemWindowInsetRight();
  1095. setPadding(leftInset, insets.getSystemWindowInsetTop(), rightInset,
  1096. insets.getSystemWindowInsetBottom());
  1097. // we're passing the insets onto the gesture handler since the back arrow is only
  1098. // conditionally added and doesn't always get all the insets.
  1099. mEdgeBackGestureHandler.setInsets(leftInset, rightInset);
  1100. // this allows assist handle to be drawn outside its bound so that it can align screen
  1101. // bottom by translating its y position.
  1102. final boolean shouldClip =
  1103. !isGesturalMode(mNavBarMode) || insets.getSystemWindowInsetBottom() == 0;
  1104. setClipChildren(shouldClip);
  1105. setClipToPadding(shouldClip);
  1106. NavigationBarController navigationBarController =
  1107. Dependency.get(NavigationBarController.class);
  1108. AssistHandleViewController controller =
  1109. navigationBarController == null
  1110. ? null : navigationBarController.getAssistHandlerViewController();
  1111. if (controller != null) {
  1112. controller.setBottomOffset(insets.getSystemWindowInsetBottom());
  1113. }
  1114. return super.onApplyWindowInsets(insets);
  1115. }
  1116. private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
  1117. pw.print(" " + caption + ": ");
  1118. if (button == null) {
  1119. pw.print("null");
  1120. } else {
  1121. pw.print(visibilityToString(button.getVisibility())
  1122. + " alpha=" + button.getAlpha()
  1123. );
  1124. }
  1125. pw.println();
  1126. }
  1127. public interface OnVerticalChangedListener {
  1128. void onVerticalChanged(boolean isVertical);
  1129. }
  1130. private final Consumer<Boolean> mDockedListener = exists -> post(() -> {
  1131. mDockedStackExists = exists;
  1132. updateRecentsIcon();
  1133. });
  1134. }

三,adb 模拟发送广播,然后底部的导航栏的图标会改变,测试效果图。

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

闽ICP备14008679号