赞
踩
1.SystemUI\src\com\android\systemui\statusbar\phone\StatusBar.java
从导航栏的入口看。
- protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
- final Context context = mContext;
- updateDisplaySize(); // populates mDisplayMetrics
- updateResources();
- updateTheme();
-
- inflateStatusBarWindow(); //将R.layout.super_status_bar布局文件构建成对应的视图。
-
- ....
-
- createNavigationBar(result); //创建导航栏
- // TODO(b/117478341): This was left such that CarStatusBar can override this method.
- // Try to remove this.
- protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
- mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
- }
2.SystemUI\src\com\android\systemui\statusbar\NavigationBarController.java
进入createNavigationBar方法,发现主要是用NavigationBarFragment来管理。
- void createNavigationBar(Display display, RegisterStatusBarResult result) {
- if (display == null) {
- return;
- }
-
- final int displayId = display.getDisplayId();
- final boolean isOnDefaultDisplay = displayId == DEFAULT_DISPLAY;
- final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
-
- try {
- if (!wms.hasNavigationBar(displayId)) {
- return;
- }
- } catch (RemoteException e) {
- // Cannot get wms, just return with warning message.
- Log.w(TAG, "Cannot get WindowManager.");
- return;
- }
- final Context context = isOnDefaultDisplay
- ? mContext
- : mContext.createDisplayContext(display);
- NavigationBarFragment.create(context, (tag, fragment) -> {
- NavigationBarFragment navBar = (NavigationBarFragment) fragment;
-
- // Unfortunately, we still need it because status bar needs LightBarController
- // before notifications creation. We cannot directly use getLightBarController()
- // from NavigationBarFragment directly.
- LightBarController lightBarController = isOnDefaultDisplay
- ? Dependency.get(LightBarController.class)
- : new LightBarController(context,
- Dependency.get(DarkIconDispatcher.class),
- Dependency.get(BatteryController.class),
- Dependency.get(NavigationModeController.class));
- navBar.setLightBarController(lightBarController);
-
- // TODO(b/118592525): to support multi-display, we start to add something which is
- // per-display, while others may be global. I think it's time to add
- // a new class maybe named DisplayDependency to solve per-display
- // Dependency problem.
- AutoHideController autoHideController = isOnDefaultDisplay
- ? Dependency.get(AutoHideController.class)
- : new AutoHideController(context, mHandler,
- Dependency.get(IWindowManager.class));
- navBar.setAutoHideController(autoHideController);
- navBar.restoreAppearanceAndTransientState();
- mNavigationBars.append(displayId, navBar);
-
- if (result != null) {
- navBar.setImeWindowStatus(display.getDisplayId(), result.mImeToken,
- result.mImeWindowVis, result.mImeBackDisposition,
- result.mShowImeSwitcher);
- }
- });
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
3.SystemUI\src\com\android\systemui\statusbar\phone\NavigationBarFragment.java
创建navigationBarView 并且把navigationBarView添加到windowManager中。
- public static View create(Context context, FragmentListener listener) {
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
- WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
- | WindowManager.LayoutParams.FLAG_SLIPPERY,
- PixelFormat.TRANSLUCENT);
- lp.token = new Binder();
- lp.setTitle("NavigationBar" + context.getDisplayId());
- lp.accessibilityTitle = context.getString(R.string.nav_bar);
- lp.windowAnimations = 0;
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
-
- View navigationBarView = LayoutInflater.from(context).inflate(
- R.layout.navigation_bar_window, null);
-
- if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
- if (navigationBarView == null) return null;
-
- final NavigationBarFragment fragment = FragmentHostManager.get(navigationBarView)
- .create(NavigationBarFragment.class);
- navigationBarView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View v) {
- final FragmentHostManager fragmentHost = FragmentHostManager.get(v);
- fragmentHost.getFragmentManager().beginTransaction()
- .replace(R.id.navigation_bar_frame, fragment, TAG)
- .commit();
- fragmentHost.addTagListener(TAG, listener);
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
- FragmentHostManager.removeAndDestroy(v);
- navigationBarView.removeOnAttachStateChangeListener(this);
- }
- });
- context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
- return navigationBarView;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
4.看下NavigationBarFragment的生命周期。onCreateView()里,导航栏的真正的rootView。
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
- Bundle savedInstanceState) {
- return inflater.inflate(R.layout.navigation_bar, container, false);
- }
5.SystemUI\res\layout\navigation_bar.xml。
进入导航栏的真正根布局:navigation_bar.xml,好吧又是自定义view,NavigationBarView和NavigationBarInflaterView都要仔细研读。
- <com.android.systemui.statusbar.phone.NavigationBarView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:background="@drawable/system_bar_background">
-
- <com.android.systemui.CornerHandleView
- android:id="@+id/assist_hint_left"
- android:layout_width="36dp"
- android:layout_height="36dp"
- android:layout_gravity="left|bottom"
- android:rotation="270"
- android:visibility="gone"/>
- <com.android.systemui.CornerHandleView
- android:id="@+id/assist_hint_right"
- android:layout_width="36dp"
- android:layout_height="36dp"
- android:layout_gravity="right|bottom"
- android:rotation="180"
- android:visibility="gone"/>
-
- <com.android.systemui.statusbar.phone.NavigationBarInflaterView
- android:id="@+id/navigation_inflater"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- </com.android.systemui.statusbar.phone.NavigationBarView>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
6.SystemUI\src\com\android\systemui\statusbar\phone\NavigationBarInflaterView.java;继承自FrameLayout
看下onFinishInflate()方法,这是view的生命周期,每个view被inflate之后都会回调。
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- inflateChildren();
- clearViews();
- inflateLayout(getDefaultLayout());
- }
-
- private void inflateChildren() {
- removeAllViews();
- mHorizontal = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout,
- this /* root */, false /* attachToRoot */);
- addView(mHorizontal);
- mVertical = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout_vertical,
- this /* root */, false /* attachToRoot */);
- addView(mVertical);
- updateAlternativeOrder();
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- protected String getDefaultLayout() {
- final int defaultResource = R.string.config_navBarLayout;/*QuickStepContract.isGesturalMode(mNavBarMode)
- ? R.string.config_navBarLayoutHandle
- : mOverviewProxyService.shouldShowSwipeUpUI()
- ? R.string.config_navBarLayoutQuickstep
- : R.string.config_navBarLayout;*/
- return getContext().getString(defaultResource);
- }
-
-
- //<!-- Nav bar button default ordering/layout -->
- <string name="config_navBarLayout" translatable="false">left;back,home,recent,screenshot;right</string>
看inflateLayout():里面的newLayout参数很重要!!!根据上一个方法看到getDefaultLayout(),他return了一个在xml写死的字符串。再看inflateLayout方法,他解析分割了xml里配置的字符串,并传给了inflateButtons方法。
- protected void inflateLayout(String newLayout) {
- mCurrentLayout = newLayout;
- if (newLayout == null) {
- newLayout = getDefaultLayout();
- }
- String[] sets = newLayout.split(GRAVITY_SEPARATOR, 3);
- if (sets.length != 3) {
- Log.d(TAG, "Invalid layout.");
- newLayout = getDefaultLayout();
- sets = newLayout.split(GRAVITY_SEPARATOR, 3);
- }
- String[] start = sets[0].split(BUTTON_SEPARATOR);
- String[] center = sets[1].split(BUTTON_SEPARATOR);
- String[] end = sets[2].split(BUTTON_SEPARATOR);
- // Inflate these in start to end order or accessibility traversal will be messed up.
- inflateButtons(start, mHorizontal.findViewById(R.id.ends_group),
- false /* landscape */, true /* start */);
- inflateButtons(start, mVertical.findViewById(R.id.ends_group),
- true /* landscape */, true /* start */);
-
- inflateButtons(center, mHorizontal.findViewById(R.id.center_group),
- false /* landscape */, false /* start */);
- inflateButtons(center, mVertical.findViewById(R.id.center_group),
- true /* landscape */, false /* start */);
-
- addGravitySpacer(mHorizontal.findViewById(R.id.ends_group));
- addGravitySpacer(mVertical.findViewById(R.id.ends_group));
-
- inflateButtons(end, mHorizontal.findViewById(R.id.ends_group),
- false /* landscape */, false /* start */);
- inflateButtons(end, mVertical.findViewById(R.id.ends_group),
- true /* landscape */, false /* start */);
-
- updateButtonDispatchersCurrentView();
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
再看inflateButtons()方法,遍历加载inflateButton:
- private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape,
- boolean start) {
- for (int i = 0; i < buttons.length; i++) {
- inflateButton(buttons[i], parent, landscape, start);
- }
- }
- @Nullable
- protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,
- boolean start) {
- LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
- View v = createView(buttonSpec, parent, inflater);
- if (v == null) return null;
-
- v = applySize(v, buttonSpec, landscape, start);
- parent.addView(v);
- addToDispatchers(v);
- View lastView = landscape ? mLastLandscape : mLastPortrait;
- View accessibilityView = v;
- if (v instanceof ReverseRelativeLayout) {
- accessibilityView = ((ReverseRelativeLayout) v).getChildAt(0);
- }
- if (lastView != null) {
- accessibilityView.setAccessibilityTraversalAfter(lastView.getId());
- }
- if (landscape) {
- mLastLandscape = accessibilityView;
- } else {
- mLastPortrait = accessibilityView;
- }
- return v;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
我们来看createView()方法:以home按键为例,加载了home的button,其实是加载了R.layout.home的layout布局。
- private View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater) {
- View v = null;
- String button = extractButton(buttonSpec);
- if (LEFT.equals(button)) {
- button = extractButton(NAVSPACE);
- } else if (RIGHT.equals(button)) {
- button = extractButton(MENU_IME_ROTATE);
- }
- if (HOME.equals(button)) {
- v = inflater.inflate(R.layout.home, parent, false);
- } else if (BACK.equals(button)) {
- v = inflater.inflate(R.layout.back, parent, false);
- } else if (RECENT.equals(button)) {
- v = inflater.inflate(R.layout.recent_apps, parent, false);
- } else if (SCREENSHOT.equals(button)) { //laiyw
- v = inflater.inflate(R.layout.screenshot, parent, false);
- } else if (MENU_IME_ROTATE.equals(button)) {
- v = inflater.inflate(R.layout.menu_ime, parent, false);
- } else if (NAVSPACE.equals(button)) {
- v = inflater.inflate(R.layout.nav_key_space, parent, false);
- } else if (CLIPBOARD.equals(button)) {
- v = inflater.inflate(R.layout.clipboard, parent, false);
- } else if (CONTEXTUAL.equals(button)) {
- v = inflater.inflate(R.layout.contextual, parent, false);
- } else if (HOME_HANDLE.equals(button)) {
- 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 (button.startsWith(KEY)) {
- String uri = extractImage(button);
- int code = extractKeycode(button);
- v = inflater.inflate(R.layout.custom_key, parent, false);
- ((KeyButtonView) v).setCode(code);
- if (uri != null) {
- if (uri.contains(":")) {
- ((KeyButtonView) v).loadAsync(Icon.createWithContentUri(uri));
- } else if (uri.contains("/")) {
- int index = uri.indexOf('/');
- String pkg = uri.substring(0, index);
- int id = Integer.parseInt(uri.substring(index + 1));
- ((KeyButtonView) v).loadAsync(Icon.createWithResource(pkg, id));
- }
- }
- }
- return v;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
7.SystemUI\res\layout\home.xml
- <com.android.systemui.statusbar.policy.KeyButtonView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/home"
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:layout_weight="0"
- systemui:keyCode="3"
- android:scaleType="center"
- android:contentDescription="@string/accessibility_home"
- android:paddingStart="@dimen/navigation_key_padding"
- android:paddingEnd="@dimen/navigation_key_padding"
- />
8.SystemUI\src\com\android\systemui\statusbar\policy\KeyButtonView.java
先来看KeyButtonView的构造方法:我们之前xml的systemui:keyCode="3"方法在这里获取。再来看Touch事件,通过sendEvent()方法可以看出,back等view的点击touch事件不是自己处理的,而是交由系统以实体按键(keycode)的形式处理的。
当然KeyButtonView类还处理了支持长按的button,按键的响声等。
- @VisibleForTesting
- public KeyButtonView(Context context, AttributeSet attrs, int defStyle, InputManager manager,
- UiEventLogger uiEventLogger) {
- super(context, attrs);
- mUiEventLogger = uiEventLogger;
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyButtonView,
- defStyle, 0);
-
- mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, KEYCODE_UNKNOWN);
-
- mPlaySounds = a.getBoolean(R.styleable.KeyButtonView_playSound, true);
-
- TypedValue value = new TypedValue();
- if (a.getValue(R.styleable.KeyButtonView_android_contentDescription, value)) {
- mContentDescriptionRes = value.resourceId;
- }
-
- a.recycle();
-
- setClickable(true);
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-
- mRipple = new KeyButtonRipple(context, this);
- mOverviewProxyService = Dependency.get(OverviewProxyService.class);
- mInputManager = manager;
- setBackground(mRipple);
- setWillNotDraw(false);
- forceHasOverlappingRendering(false);
- }
-
-
-
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- final boolean showSwipeUI = mOverviewProxyService.shouldShowSwipeUpUI();
- final int action = ev.getAction();
- int x, y;
- if (action == MotionEvent.ACTION_DOWN) {
- mGestureAborted = false;
- }
- if (mGestureAborted) {
- setPressed(false);
- return false;
- }
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mDownTime = SystemClock.uptimeMillis();
- mLongClicked = false;
- setPressed(true);
-
- // Use raw X and Y to detect gestures in case a parent changes the x and y values
- mTouchDownX = (int) ev.getRawX();
- mTouchDownY = (int) ev.getRawY();
- if (mCode != KEYCODE_UNKNOWN) {
- sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
- } else {
- // Provide the same haptic feedback that the system offers for virtual keys.
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
- }
- if (!showSwipeUI) {
- playSoundEffect(SoundEffectConstants.CLICK);
- }
- removeCallbacks(mCheckLongPress);
- postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
- break;
- case MotionEvent.ACTION_MOVE:
- x = (int)ev.getRawX();
- y = (int)ev.getRawY();
-
- float slop = QuickStepContract.getQuickStepTouchSlopPx(getContext());
- if (Math.abs(x - mTouchDownX) > slop || Math.abs(y - mTouchDownY) > slop) {
- // When quick step is enabled, prevent animating the ripple triggered by
- // setPressed and decide to run it on touch up
- setPressed(false);
- removeCallbacks(mCheckLongPress);
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- setPressed(false);
- if (mCode != KEYCODE_UNKNOWN) {
- sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
- }
- removeCallbacks(mCheckLongPress);
- break;
- case MotionEvent.ACTION_UP:
- final boolean doIt = isPressed() && !mLongClicked;
- setPressed(false);
- final boolean doHapticFeedback = (SystemClock.uptimeMillis() - mDownTime) > 150;
- if (showSwipeUI) {
- if (doIt) {
- // Apply haptic feedback on touch up since there is none on touch down
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
- playSoundEffect(SoundEffectConstants.CLICK);
- }
- } else if (doHapticFeedback && !mLongClicked) {
- // Always send a release ourselves because it doesn't seem to be sent elsewhere
- // and it feels weird to sometimes get a release haptic and other times not.
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
- }
- if (mCode != KEYCODE_UNKNOWN) {
- if (doIt) {
- sendEvent(KeyEvent.ACTION_UP, 0);
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
- } else {
- sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
- }
- } else {
- // no key code, just a regular ImageView
- if (doIt && mOnClickListener != null) {
- mOnClickListener.onClick(this);
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
- }
- }
- removeCallbacks(mCheckLongPress);
- break;
- }
-
- return true;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- private void sendEvent(int action, int flags, long when) {
- mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_NAV_BUTTON_EVENT)
- .setType(MetricsEvent.TYPE_ACTION)
- .setSubtype(mCode)
- .addTaggedData(MetricsEvent.FIELD_NAV_ACTION, action)
- .addTaggedData(MetricsEvent.FIELD_FLAGS, flags));
- logSomePresses(action, flags);
- if (mCode == KeyEvent.KEYCODE_BACK && flags != KeyEvent.FLAG_LONG_PRESS) {
- Log.i(TAG, "Back button event: " + KeyEvent.actionToString(action));
- if (action == MotionEvent.ACTION_UP) {
- mOverviewProxyService.notifyBackAction((flags & KeyEvent.FLAG_CANCELED) == 0,
- -1, -1, true /* isButton */, false /* gestureSwipeLeft */);
- }
- }
- final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
- final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
- 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
- flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
- InputDevice.SOURCE_KEYBOARD);
-
- int displayId = INVALID_DISPLAY;
-
- // Make KeyEvent work on multi-display environment
- if (getDisplay() != null) {
- displayId = getDisplay().getDisplayId();
- }
- // Bubble controller will give us a valid display id if it should get the back event
- BubbleController bubbleController = Dependency.get(BubbleController.class);
- int bubbleDisplayId = bubbleController.getExpandedDisplayId(mContext);
- if (mCode == KeyEvent.KEYCODE_BACK && bubbleDisplayId != INVALID_DISPLAY) {
- displayId = bubbleDisplayId;
- }
- if (displayId != INVALID_DISPLAY) {
- ev.setDisplayId(displayId);
- }
- mInputManager.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
9.那么我们现在布局文件都添加完成了,但是你会发现在NavigationBarInflaterView没有对资源文件添加的代码已经控件点击触摸事件处理逻辑。那么这两部分代码在哪里呢?
答案是:
1.NavigationBarView 完成资源文件添加。
2.NavigationBarFragment 添加点击事件和触摸事件的处理逻辑。
9.1.SystemUI\src\com\android\systemui\statusbar\phone\NavigationBarView.java
进入NavigationBarView类里,找到构造方法。
- public NavigationBarView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- ...
- ....
-
- //mButtonDispatchers 是维护这些home back recent图标view的管理类,会传递到他的child,NavigationBarInflaterView类中
- mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
- mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
- mButtonDispatchers.put(R.id.screenshot, new ButtonDispatcher(R.id.screenshot));
- mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
- mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
- mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
- mButtonDispatchers.put(R.id.accessibility_button, accessibilityButton);
- mButtonDispatchers.put(R.id.rotate_suggestion, rotateSuggestionButton);
- mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
- mDeadZone = new DeadZone(this);
-
- ......
-
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- @Override
- public void onFinishInflate() {
- super.onFinishInflate();
- mNavigationInflaterView = findViewById(R.id.navigation_inflater);
- mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
-
- getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
-
- Divider divider = Dependency.get(Divider.class);
- divider.registerInSplitScreenListener(mDockedListener);
- updateOrientationViews();
- reloadNavIcons(); //加载图片
- }
- 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);
- mScreenshot = getDrawable(R.drawable.ic_sysbar_shotscreen);
- mContextualButtonGroup.updateIcons();
- }
- if (orientationChange || densityChange || dirChange) {
- mBackIcon = getBackDrawable();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
9.2.SystemUI\src\com\android\systemui\statusbar\phone\NavigationBarFragment.java
- @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();
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- 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();
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
至此,SystemUI的虚拟导航栏模块代码流程结束。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。