赞
踩
WindowInsets源码解释为Window Content的一系列插值集合,可以理解为可以将其理解为不同的窗口装饰区域类型,比如一个Activity相对于手机屏幕需要空出的地方以腾给StatusBar、Ime、NavigationBar等系统窗口,具体表现为该区域需要的上下左右的宽高。
WindowInsets包括三类:SystemWindowInsets、StableInsets、WIndowDecorInsets
1、保存系统中所有的Insets的状态,他是状态描述者,持有系统中可以产生Window Insets的window状态,它主要持有以下几种类型的Insets:
frameworks/base/core/java/android/view/InsetsState.java
public class InsetsState implements Parcelable { public static final int ITYPE_INVALID = -1; static final int FIRST_TYPE = 0; public static final int ITYPE_STATUS_BAR = FIRST_TYPE;//状态栏 public static final int ITYPE_NAVIGATION_BAR = 1;//导航栏 public static final int ITYPE_CAPTION_BAR = 2; public static final int ITYPE_TOP_GESTURES = 3; public static final int ITYPE_BOTTOM_GESTURES = 4; public static final int ITYPE_LEFT_GESTURES = 5; public static final int ITYPE_RIGHT_GESTURES = 6; public static final int ITYPE_TOP_MANDATORY_GESTURES = 7; public static final int ITYPE_BOTTOM_MANDATORY_GESTURES = 8; public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9; public static final int ITYPE_RIGHT_MANDATORY_GESTURES = 10; public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 11; public static final int ITYPE_TOP_DISPLAY_CUTOUT = 12; public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 13; public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 14; public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 15; public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 16; public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 17; public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 18; public static final int ITYPE_IME = 19;//输入法 public static final int ITYPE_CLIMATE_BAR = 20; public static final int ITYPE_EXTRA_NAVIGATION_BAR = 21; static final int LAST_TYPE = ITYPE_EXTRA_NAVIGATION_BAR; public static final int SIZE = LAST_TYPE + 1; //mSources变量维护所有产生Insets的window(也就是InsetsSource)的状态。 private final InsetsSource[] mSources = new InsetsSource[SIZE]; }
1、InsetsState发生变化的时候,会回调ViewRootImpl的内部类W的insetsChanged方法,相关代码如下所示。
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks, AttachedSurfaceControl { static class W extends IWindow.Stub { private final WeakReference<ViewRootImpl> mViewAncestor; private final IWindowSession mWindowSession; W(ViewRootImpl viewAncestor) { mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor); mWindowSession = viewAncestor.mWindowSession; } //Insets发生了变化 @Override public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { //触发ViewRootImpl的dispatchInsetsChanged方法 viewAncestor.dispatchInsetsChanged(insetsState, willMove, willResize); } } } //ViewRootImpl的内部Handler final ViewRootHandler mHandler = new ViewRootHandler(); private void dispatchInsetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) { if (Binder.getCallingPid() == android.os.Process.myPid()) { insetsState = new InsetsState(insetsState, true /* copySource */); } if (mTranslator != null) { mTranslator.translateInsetsStateInScreenToAppWindow(insetsState); } if (insetsState != null && insetsState.getSourceOrDefaultVisibility(ITYPE_IME)) { ImeTracing.getInstance().triggerClientDump("ViewRootImpl#dispatchInsetsChanged", getInsetsController().getHost().getInputMethodManager(), null /* icProto */); } SomeArgs args = SomeArgs.obtain(); args.arg1 = insetsState; args.argi1 = willMove ? 1 : 0; args.argi2 = willResize ? 1 : 0; //发送MSG_INSETS_CHANGED消息事件,触发ViewRootHandler的handleMessage方法。 mHandler.obtainMessage(MSG_INSETS_CHANGED, args).sendToTarget(); } //系统Insets的控制器 private final InsetsController mInsetsController; final class ViewRootHandler extends Handler { @Override public void handleMessage(Message msg) { try { handleMessageImpl(msg); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } private void handleMessageImpl(Message msg) { switch (msg.what) { ...代码省略... case MSG_INSETS_CHANGED: { SomeArgs args = (SomeArgs) msg.obj; mWillMove = args.argi1 == 1; mWillResize = args.argi2 == 1; //触发InsetsController的onStateChanged方法 mInsetsController.onStateChanged((InsetsState) args.arg1); args.recycle(); break; } ...代码省略... } } }
ViewRootImpl经过层层调用,最终会调用InsetsController的onStateChanged方法。
2、InsetsController的onStateChanged方法如下所示。
frameworks/base/core/java/android/view/InsetsController.java
public class InsetsController implements WindowInsetsController, InsetsAnimationControlCallbacks { public boolean onStateChanged(InsetsState state) { boolean stateChanged = !mState.equals(state, true /* excludingCaptionInsets */, false /* excludeInvisibleIme */) || !captionInsetsUnchanged(); if (!stateChanged && mLastDispatchedState.equals(state)) { return false; } if (DEBUG) Log.d(TAG, "onStateChanged: " + state); mLastDispatchedState.set(state, true /* copySources */); final InsetsState lastState = new InsetsState(mState, true /* copySources */); updateState(state); applyLocalVisibilityOverride(); if (!mState.equals(lastState, false /* excludingCaptionInsets */, true /* excludeInvisibleIme */)) { if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged"); mHost.notifyInsetsChanged(); startResizingAnimationIfNeeded(lastState); } return true; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。