什么是 WindowInsets?
What are WindowInsets?
我正在尝试了解 Android OS,在阅读 Google I/O 2014 应用程序时,我遇到了 WindowInsets
.如果有人能解释它们是什么,那将是一个很大的帮助。谢谢。
您可以了解有关 WindowInsets here. WindowInsets
provides you with the area on the window that is usable by the application. By itself it's of not much use. It's true purpose comes when you either override View.onApplyWindowInsets
or implement View.OnApplyWindowInsetsListener
. You can read about them here: View.onApplyWindowInsets and View.OnApplyWindowInsetsListener 的所有信息。
Listener for applying window insets on a view in a custom way.
Apps may choose to implement this interface if they want to apply
custom policy to the way that window insets are treated for a view. If
an OnApplyWindowInsetsListener is set, its onApplyWindowInsets method
will be called instead of the View's own onApplyWindowInsets method.
The listener may optionally call the parameter View's
onApplyWindowInsets method to apply the View's normal behavior as part
of its own.
简而言之,重写它可以让您控制 window 可用于您的视图的区域。
WindowInsets
是应用于 window.
的系统视图(例如状态栏、导航栏)的插图(或大小)
举个具体的例子就很容易理解了。想象这个场景:
现在,您不希望将 WindowInsets
应用于背景 ImageView
,因为在这种情况下 ImageView
会被状态栏高度填充。
但您确实希望将插图应用于 Toolbar
,否则 Toolbar
会绘制在状态栏中间的某处。
视图声明希望在 xml 中应用 WindowInsets
,方法是:
android:fitsSystemWindows="true"
在此示例中,您不能将 WindowInsets
应用于根布局,因为根布局会占用 WindowInsets
,并且 ImageView
会被填充。
相反,您可以使用 ViewCompat.setOnApplyWindowInsetsListener
将插图应用于工具栏:
ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) -> {
((ViewGroup.MarginLayoutParams) v.getLayoutParams()).topMargin =
insets.getSystemWindowInsetTop();
return insets.consumeSystemWindowInsets();
});
请注意,当 Toolbar
的根布局将 WindowsInsets
传递给其子级时,将调用此回调。 FrameLayout
、LinearLayout
等布局不会,DrawerLayout
、CoordinatorLayout
会。
您可以子类化您的布局,例如FrameLayout
并覆盖 onApplyWindowInsets
:
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
int childCount = getChildCount();
for (int index = 0; index < childCount; index++)
getChildAt(index).dispatchApplyWindowInsets(insets); // let children know about WindowInsets
return insets;
}
Chris Banes 做了 nice blog post at medium by Ian Lake concerning this stuff, also "Becoming a master window fitter" 演示。
我还创建了 a detailed article at Medium 关于 WindowInset
s.
更多资源:
Android系统使用屏幕的某些部分来呈现自己的内容,例如顶部的状态栏和底部的导航栏。例如,如果一个应用程序想要在底部栏后面渲染,它应该考虑底部栏所占用的区域,否则应用程序 UI 将与系统 UI 发生冲突,你会得到一些东西像这样¹:
在上图中,应向 FAB 按钮添加一个额外的底部边距,这样按钮就不会与底部栏相交。 WindowInsets API allows you to get such information as the bottom inset that the system UI consumes. You can often come across fitsSystemWindows
attribute which serves a similar purpose, see this answer for more information about the attribute and when you should use it instead of WindowInsets
. You can also take a look at this great article: Gesture Navigation: handling visual overlaps (II)。等等,什么是手势导航?
好吧,视觉重叠并不是您可能面临的唯一问题。由于 Android 10 (API 29) 添加了新的 Gesture Navigation 模式。现在,用户可以选择使用手势在应用程序之间导航,而不是像上图那样使用按钮栏。现在强烈建议应用程序在导航栏后面绘制,以便用户拥有更现代的用户体验。但除此之外,还引入了一种新的插入类型——手势插入。事实证明,如果选择 Gesture Navigation 模式,应用程序手势可能会与系统手势冲突。例如,让我们看看下面的图片²:
如您所见,搜索栏太靠近底部边缘,与系统 quick-switch 手势冲突。由于系统手势具有更高的优先级,搜索栏变得不可用。此示例以及其他常见场景在 Gesture Navigation: handling gesture conflicts (III) 文章中有详细描述。
我上面提到的文章是 Gesture Navigation series written by Chris Banes who works in the Android team. If you want to get a deeper understanding of the theme, I recommend you read the whole series. Another article Animating your keyboard (part 1) 的一部分可能也有帮助,它描述了 WindowInsets API 以及新的 IME 插入类型的持续变化。
参考:
- Gesture Navigation series
- What exactly does fitsSystemWindows do?
- Animating your keyboard (part 1)
- WindowInsets — listeners to layouts
- Why would I want to fitsSystemWindows?
- Becoming a master window fitter (droidcon London 2017)
¹ 图片来自Gesture Navigation: going edge-to-edge (I)文章
² 图片来自Gesture Navigation: handling gesture conflicts (III)文章
我正在尝试了解 Android OS,在阅读 Google I/O 2014 应用程序时,我遇到了 WindowInsets
.如果有人能解释它们是什么,那将是一个很大的帮助。谢谢。
您可以了解有关 WindowInsets here. WindowInsets
provides you with the area on the window that is usable by the application. By itself it's of not much use. It's true purpose comes when you either override View.onApplyWindowInsets
or implement View.OnApplyWindowInsetsListener
. You can read about them here: View.onApplyWindowInsets and View.OnApplyWindowInsetsListener 的所有信息。
Listener for applying window insets on a view in a custom way.
Apps may choose to implement this interface if they want to apply custom policy to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener is set, its onApplyWindowInsets method will be called instead of the View's own onApplyWindowInsets method. The listener may optionally call the parameter View's onApplyWindowInsets method to apply the View's normal behavior as part of its own.
简而言之,重写它可以让您控制 window 可用于您的视图的区域。
WindowInsets
是应用于 window.
举个具体的例子就很容易理解了。想象这个场景:
现在,您不希望将 WindowInsets
应用于背景 ImageView
,因为在这种情况下 ImageView
会被状态栏高度填充。
但您确实希望将插图应用于 Toolbar
,否则 Toolbar
会绘制在状态栏中间的某处。
视图声明希望在 xml 中应用 WindowInsets
,方法是:
android:fitsSystemWindows="true"
在此示例中,您不能将 WindowInsets
应用于根布局,因为根布局会占用 WindowInsets
,并且 ImageView
会被填充。
相反,您可以使用 ViewCompat.setOnApplyWindowInsetsListener
将插图应用于工具栏:
ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) -> {
((ViewGroup.MarginLayoutParams) v.getLayoutParams()).topMargin =
insets.getSystemWindowInsetTop();
return insets.consumeSystemWindowInsets();
});
请注意,当 Toolbar
的根布局将 WindowsInsets
传递给其子级时,将调用此回调。 FrameLayout
、LinearLayout
等布局不会,DrawerLayout
、CoordinatorLayout
会。
您可以子类化您的布局,例如FrameLayout
并覆盖 onApplyWindowInsets
:
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
int childCount = getChildCount();
for (int index = 0; index < childCount; index++)
getChildAt(index).dispatchApplyWindowInsets(insets); // let children know about WindowInsets
return insets;
}
Chris Banes 做了 nice blog post at medium by Ian Lake concerning this stuff, also "Becoming a master window fitter" 演示。
我还创建了 a detailed article at Medium 关于 WindowInset
s.
更多资源:
Android系统使用屏幕的某些部分来呈现自己的内容,例如顶部的状态栏和底部的导航栏。例如,如果一个应用程序想要在底部栏后面渲染,它应该考虑底部栏所占用的区域,否则应用程序 UI 将与系统 UI 发生冲突,你会得到一些东西像这样¹:
在上图中,应向 FAB 按钮添加一个额外的底部边距,这样按钮就不会与底部栏相交。 WindowInsets API allows you to get such information as the bottom inset that the system UI consumes. You can often come across fitsSystemWindows
attribute which serves a similar purpose, see this answer for more information about the attribute and when you should use it instead of WindowInsets
. You can also take a look at this great article: Gesture Navigation: handling visual overlaps (II)。等等,什么是手势导航?
好吧,视觉重叠并不是您可能面临的唯一问题。由于 Android 10 (API 29) 添加了新的 Gesture Navigation 模式。现在,用户可以选择使用手势在应用程序之间导航,而不是像上图那样使用按钮栏。现在强烈建议应用程序在导航栏后面绘制,以便用户拥有更现代的用户体验。但除此之外,还引入了一种新的插入类型——手势插入。事实证明,如果选择 Gesture Navigation 模式,应用程序手势可能会与系统手势冲突。例如,让我们看看下面的图片²:
如您所见,搜索栏太靠近底部边缘,与系统 quick-switch 手势冲突。由于系统手势具有更高的优先级,搜索栏变得不可用。此示例以及其他常见场景在 Gesture Navigation: handling gesture conflicts (III) 文章中有详细描述。
我上面提到的文章是 Gesture Navigation series written by Chris Banes who works in the Android team. If you want to get a deeper understanding of the theme, I recommend you read the whole series. Another article Animating your keyboard (part 1) 的一部分可能也有帮助,它描述了 WindowInsets API 以及新的 IME 插入类型的持续变化。
参考:
- Gesture Navigation series
- What exactly does fitsSystemWindows do?
- Animating your keyboard (part 1)
- WindowInsets — listeners to layouts
- Why would I want to fitsSystemWindows?
- Becoming a master window fitter (droidcon London 2017)
¹ 图片来自Gesture Navigation: going edge-to-edge (I)文章
² 图片来自Gesture Navigation: handling gesture conflicts (III)文章