Android 12 S WindowInset解析

12 篇文章 3 订阅
9 篇文章 1 订阅

4d80cb7d13214d4e994176b265b322f4.png

  WindowInsetsStateController
    InsetsState
      mDisplayFrame=Rect(0, 0 - 1080, 2280)
      mDisplayCutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]} cutoutPathParserInfo={CutoutPathParserInfo{displayWidth=0 displayHeight=0 density={0.0} cutoutSpec={} rotation={0} scale={0.0}}}}
      mRoundedCorners=RoundedCorners{[RoundedCorner{position=TopLeft, radius=0, center=Point(0, 0)}, RoundedCorner{position=TopRight, radius=0, center=Point(0, 0)}, RoundedCorner{position=BottomRight, radius=0, center=Point(0, 0)}, RoundedCorner{position=BottomLeft, radius=0, center=Point(0, 0)}]}
      mPrivacyIndicatorBounds=PrivacyIndicatorBounds {static bounds=Rect(816, 0 - 1042, 66) rotation=0}
        InsetsSource type=ITYPE_STATUS_BAR frame=[0,0][1080,66] visible=true
        InsetsSource type=ITYPE_NAVIGATION_BAR frame=[0,2148][1080,2280] visible=true
        InsetsSource type=ITYPE_LEFT_GESTURES frame=[0,0][0,2280] visible=true
        InsetsSource type=ITYPE_RIGHT_GESTURES frame=[1080,0][1080,2280] visible=true
        InsetsSource type=ITYPE_TOP_MANDATORY_GESTURES frame=[0,0][1080,66] visible=true
        InsetsSource type=ITYPE_BOTTOM_MANDATORY_GESTURES frame=[0,2148][1080,2280] visible=true
        InsetsSource type=ITYPE_TOP_TAPPABLE_ELEMENT frame=[0,0][1080,66] visible=true
        InsetsSource type=ITYPE_BOTTOM_TAPPABLE_ELEMENT frame=[0,2148][1080,2280] visible=true
        InsetsSource type=ITYPE_IME frame=[0,0][0,0] visible=false
    Control map:
      ITYPE_IME -> Window{a3c1e78 u0 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
      ITYPE_NAVIGATION_BAR -> Window{a3c1e78 u0 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
      ITYPE_STATUS_BAR -> Window{a3c1e78 u0 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
    InsetsSourceProviders:
      ImeInsetsSourceProvider
        mSource=InsetsSource type=ITYPE_IME frame=[0,0][0,0] visible=false
        mControl=InsetsSourceControl type=ITYPE_IME mLeash=Surface(name=Surface(name=b1bcc7e InputMethod)/@0xca4328a - animation-leash of insets_animation)/@0x486b990 mSurfacePosition=Point(0, 66) mInsetsHint=Insets{left=0, top=0, right=0, bottom=0} mSkipAnimationOnce=false
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,0][0,0]
        mWin=Window{b1bcc7e u0 InputMethod}
        mAdapter=ControlAdapter mCapturedLeash=Surface(name=Surface(name=b1bcc7e InputMethod)/@0xca4328a - animation-leash of insets_animation)/@0x486b990
        mControlTarget=Window{a3c1e78 u0 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
        mImeShowing=false
      InsetsSourceProvider
        mSource=InsetsSource type=ITYPE_BOTTOM_TAPPABLE_ELEMENT frame=[0,2148][1080,2280] visible=true
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,0][0,0]
        mWin=Window{e5c508e u0 NavigationBar0}
      InsetsSourceProvider
        mSource=InsetsSource type=ITYPE_TOP_TAPPABLE_ELEMENT frame=[0,0][1080,66] visible=true
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,0][0,0]
        mWin=Window{6498fc2 u0 StatusBar}
      InsetsSourceProvider
        mSource=InsetsSource type=ITYPE_BOTTOM_MANDATORY_GESTURES frame=[0,2148][1080,2280] visible=true
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,0][0,0]
        mWin=Window{e5c508e u0 NavigationBar0}
      InsetsSourceProvider
        mSource=InsetsSource type=ITYPE_TOP_MANDATORY_GESTURES frame=[0,0][1080,66] visible=true
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,0][0,0]
        mWin=Window{6498fc2 u0 StatusBar}
      InsetsSourceProvider
        mSource=InsetsSource type=ITYPE_RIGHT_GESTURES frame=[1080,0][1080,2280] visible=true
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,0][0,0]
        mWin=Window{e5c508e u0 NavigationBar0}
      InsetsSourceProvider
        mSource=InsetsSource type=ITYPE_LEFT_GESTURES frame=[0,0][0,2280] visible=true
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,0][0,0]
        mWin=Window{e5c508e u0 NavigationBar0}
      InsetsSourceProvider
        mSource=InsetsSource type=ITYPE_NAVIGATION_BAR frame=[0,2148][1080,2280] visible=true
        mControl=InsetsSourceControl type=ITYPE_NAVIGATION_BAR mLeash=Surface(name=Surface(name=e5c508e NavigationBar0)/@0x7b6d4d9 - animation-leash of insets_animation)/@0xf471289 mSurfacePosition=Point(0, 2148) mInsetsHint=Insets{left=0, top=0, right=0, bottom=132} mSkipAnimationOnce=false
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,2148][1080,2280]
        mWin=Window{e5c508e u0 NavigationBar0}
        mAdapter=ControlAdapter mCapturedLeash=Surface(name=Surface(name=e5c508e NavigationBar0)/@0x7b6d4d9 - animation-leash of insets_animation)/@0xf471289
        mControlTarget=Window{a3c1e78 u0 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
      InsetsSourceProvider
        mSource=InsetsSource type=ITYPE_STATUS_BAR frame=[0,0][1080,66] visible=true
        mControl=InsetsSourceControl type=ITYPE_STATUS_BAR mLeash=Surface(name=Surface(name=6498fc2 StatusBar)/@0x2e26b41 - animation-leash of insets_animation)/@0x7ded28e mSurfacePosition=Point(0, 0) mInsetsHint=Insets{left=0, top=66, right=0, bottom=0} mSkipAnimationOnce=false
        mIsLeashReadyForDispatching=true mImeOverrideFrame=[0,0][0,0]
        mWin=Window{6498fc2 u0 StatusBar}
        mAdapter=ControlAdapter mCapturedLeash=Surface(name=Surface(name=6498fc2 StatusBar)/@0x2e26b41 - animation-leash of insets_animation)/@0x7ded28e
        mControlTarget=Window{a3c1e78 u0 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
 

WindowInsets: 

源码解释:Describes a set of insets for window content.

WindowInsets are immutable and may be expanded to include more inset types in the future.  To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance* with the adjusted properties.

window content的一系列inset,可以理解为 一个Activity相对于手机屏幕需要空出的地方以腾纳给statusbar、Ime、Navigationbar等系统窗口,具体表现为该区域需要的上下左右的宽高,比如输入法窗口的区域就是一个Inset)

InsetsState:

Holder for state of system windows that cause window insets for all other windows in the system.

WindowInsets包括三类:SystemWindowInsets、StableInsets、WIndowDecorInsets

  • SystemWindowInsets:全窗口下,被navigationbar、statusbar、ime或其他系统窗口覆盖的区域
  • StableInsets:全窗口下,被系统UI覆盖的区域
  • WIndowDecorInsets:系统预留属性

如果开发者绘制的内容出现在了系统 UI 区域内,就可能出现视觉与手势的冲突。开发者可以借助 Insets 把 view 从屏幕边缘向内移动到一个合适的位置。不要把 Insets 的 topbottomleftright 与 Rect 的搞混,前者描述的是偏移,后者是坐标

在源码中,Insets 对象拥有 4 个 int 值,用于描述矩形四个边的偏移

Inset Type

Inset

Type

Vlaue

Public TypePublic Type Value含义
ITYPE_INVALID-1
FIRST_TYPE0
FIRST1 << 0
ITYPE_STATUS_BAR

FIRST_TYPE

STATUS_BARSFIRST状态栏
ITYPE_NAVIGATION_BAR1NAVIGATION_BARS1 << 1导航栏
ITYPE_CAPTION_BAR2CAPTION_BAR1 << 2标题栏
ITYPE_TOP_GESTURES3SYSTEM_GESTURES1 << 4系统手势边衬区
ITYPE_BOTTOM_GESTURES4
ITYPE_LEFT_GESTURES5
ITYPE_RIGHT_GESTURES6
ITYPE_TOP_MANDATORY_GESTURES7

MANDATORY_SYSTEM

_GESTURES

1 << 5强制系统手势边衬区
ITYPE_BOTTOM_MANDATORY_GESTURES8
ITYPE_LEFT_MANDATORY_GESTURES9
ITYPE_RIGHT_MANDATORY_GESTURES10
ITYPE_LEFT_DISPLAY_CUTOUT11DISPLAY_CUTOUT1 << 7刘海屏
ITYPE_TOP_DISPLAY_CUTOUT12
ITYPE_RIGHT_DISPLAY_CUTOUT13
ITYPE_BOTTOM_DISPLAY_CUTOUT14
ITYPE_LEFT_TAPPABLE_ELEMENT15TAPPABLE_ELEMENT1 << 6可点击区域
ITYPE_TOP_TAPPABLE_ELEMENT16
ITYPE_RIGHT_TAPPABLE_ELEMENT17
ITYPE_BOTTOM_TAPPABLE_ELEMENT18
ITYPE_IME19IME1 << 3输入法
ITYPE_CLIMATE_BAR20STATUS_BARS
ITYPE_EXTRA_NAVIGATION_BAR21NAVIGATION_BARS
LAST_TYPE

ITYPE_EXTRA

_NAVIGATION

_BAR

LAST1 << 8
WINDOW_DECORLAST

在Android10以上的系统中,我们可以通过调用以下代码来隐藏状态栏和导航栏。

   //获取WindowInsetsController对象实例
    WindowInsetsController windowInsetsController = getWindow().getDecorView().getWindowInsetsController();
    //调用hide隐藏状态栏
    windowInsetsController.hide(WindowInsets.Type.statusBars())
    //调用hide隐藏导航栏
    windowInsetsController.hide(WindowInsets.Type.navigationBar())
    //调用show显示状态栏
    windowInsetsController.show(WindowInsets.Type.statusBars())
    //调用show显示导航栏
    windowInsetsController.show(WindowInsets.Type.navigationBar())

 在 Android R 之前,获取状态栏高度通常是通过反射获取。但是有了 WindowInsets 就不用这么麻烦了:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = findViewById(R.id.TextView);
        textView.getWindowInsetsController().hide(WindowInsets.Type.navigationBars());
        textView.getWindowInsetsController().hide(WindowInsets.Type.statusBars());

    }

 效果如下:

4e49233e107c40e79e1b5d8ad27ae248.png

返回刘海边衬区

    /**
     * Returns the display cutout if there is one.
     *
     * <p>Note: the display cutout will already be {@link #consumeDisplayCutout consumed} during dispatch to {@link View#onApplyWindowInsets}, unless the window has requested a
     * {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode} other than
     * {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER never} or
     * {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT default}.
     *
     * @return the display cutout or null if there is none
     * @see DisplayCutout
     */
    @Nullable
    public DisplayCutout getDisplayCutout() {
        return mDisplayCutout;
    }

返回以像素为单位的稳定insets

    /**
     * Returns the stable insets in pixels.
     *
     * <p>The stable inset represents the area of a full-screen window that <b>may</b> be partially or fully obscured by the system UI elements.  This value does not change based on the visibility state of those elements; for example, if the status bar is normally shown, but temporarily hidden, the stable inset will still provide the inset associated with the status bar being shown.</p>
     * @return The stable insets
     * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
     * instead.
     */
    @Deprecated
    @NonNull
    public Insets getStableInsets() {
        return getInsets(mTypeMaxInsetsMap, mCompatInsetsTypes);
    }

返回系统手势insets区域

    /**
     * Returns the system gesture insets.
     *
     * <p>The system gesture insets represent the area of a window where system gestures have priority and may consume some or all touch input, e.g. due to the a system bar occupying it, or it being reserved for touch-only gestures.
     *
     * <p>An app can declare priority over system gestures with
     * {@link View#setSystemGestureExclusionRects} outside of the
     * {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}.
     *
     * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the exclusions it takes into account. The limit does not apply while the navigation bar is {@link View#SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the {@link android.inputmethodservice.InputMethodService input method} and
     * {@link Intent#CATEGORY_HOME home activity}.
     * </p>
     * <p>Simple taps are guaranteed to reach the window even within the system gesture insets, as long as they are outside the {@link #getTappableElementInsets() system window insets}.
     *
     * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned even when the system gestures are inactive due to
     * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
     * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
     *
     * <p>This inset is consumed together with the {@link #getSystemWindowInsets() system window insets} by {@link #consumeSystemWindowInsets()}.
     *
     * @see #getMandatorySystemGestureInsets
     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemGestures()} instead.
     */
    @Deprecated
    @NonNull
    public Insets getSystemGestureInsets() {
        return getInsets(mTypeInsetsMap, SYSTEM_GESTURES);
    }

返回以piexl为单位的系统window insets

    /**
     * Returns the system window insets in pixels.
     *
     * <p>The system window inset represents the area of a full-screen window that is partially or fully obscured by the status bar, navigation bar, IME or other system windows.
     * @return The system window insets
     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()} instead.
     */
    @Deprecated
    @NonNull
    public Insets getSystemWindowInsets() {
        Insets result = mCompatIgnoreVisibility
                ? getInsetsIgnoringVisibility(mCompatInsetsTypes & ~ime())
                : getInsets(mCompatInsetsTypes);

        // We can't query max insets for IME, so we need to add it manually after.
        if ((mCompatInsetsTypes & ime()) != 0 && mCompatIgnoreVisibility) {
            result = Insets.max(result, getInsets(ime()));
        }
        return result;
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值