gpt4 book ai didi

android - 使用 WindowInsets 在 Android 上正确进行边到边处理

转载 作者:行者123 更新时间:2023-12-03 23:12:30 28 4
gpt4 key购买 nike

我正在尝试让边缘到边缘( https://youtu.be/OCHEjeLC_UY?t=1635 )在 API 21 到 29 上正常工作。

我在我的 v27\themes.xml 上使用它:

<item name="android:windowLightNavigationBar">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>

这在我的 Activity 中:
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)

if (hasFocus) {
window.decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
}

另外,我正在设置 android:fitsSystemWindows=true在我的 AppBarLayout .

有了这个,它在 API >= 27 上看起来很好,其中内容在现在透明的导航栏后面滚动,但在旧 API 上,内容被黑色导航栏覆盖。

我知道我需要获得 WindowInsets并将其添加到我现有的填充中(或者在 AppBarLayout 的情况下,它将自己处理插图),但我无法让它与 FAB 一起使用。

我找到了 this article关于将插图添加到 padding的观点,但因为 FAB 使用 margin我不确定,如果我在正确的轨道上。

是否有任何文档,例如,关于如何在边缘到边缘处理插入的最佳实践?似乎有些小部件像 AppBarLayout优雅地处理它,但我怎样才能让 FAB 也调整它的边距?

更新 1

添加时要指定 android:fitsSystemWindows=trueCoordinatorLayout它也处理插图,但有一个主要缺点:

我有两个布局,每个都有 CoordinatorLayout : “父布局”定义了 CoordinatorLayoutAppBarLayoutFrameLayout保存放置在后者中的 Fragment 使用的实际内容和“子布局”。

因此,我无法添加 android:fitsSystemWindows=true到子布局,因为它会导致顶部(工具栏和内容之间)有一个空白空间,我不能把它放在父布局中,因为这样 FAB 不会更新到插图。

最佳答案

编辑 2022-01-16:
现在我们可以使用https://google.github.io/accompanist/insets获取jetpack compose的插图,只需添加WindowCompat.setDecorFitsSystemWindows(window, false)像@shogun-nassar 在 his answer 中正确指出.

原答案:
提供最终答案:
不要使用 android:fitsSystemWindows除了手动将插图应用到屏幕边缘的任何 View 之外的任何地方,否则它们会滑到系统栏后面(例如 AppBarLayoutFloatingActionButton )。
我写了一些助手来将插图添加到填充或边距,尊重之前添加的任何一个(需要 androidx.core:core:1.2.0-alpha01):

fun View.addSystemWindowInsetToPadding(
left: Boolean = false,
top: Boolean = false,
right: Boolean = false,
bottom: Boolean = false
) {
val (initialLeft, initialTop, initialRight, initialBottom) =
listOf(paddingLeft, paddingTop, paddingRight, paddingBottom)

ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets ->
view.updatePadding(
left = initialLeft + (if (left) insets.systemWindowInsetLeft else 0),
top = initialTop + (if (top) insets.systemWindowInsetTop else 0),
right = initialRight + (if (right) insets.systemWindowInsetRight else 0),
bottom = initialBottom + (if (bottom) insets.systemWindowInsetBottom else 0)
)

insets
}
}

fun View.addSystemWindowInsetToMargin(
left: Boolean = false,
top: Boolean = false,
right: Boolean = false,
bottom: Boolean = false
) {
val (initialLeft, initialTop, initialRight, initialBottom) =
listOf(marginLeft, marginTop, marginRight, marginBottom)

ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets ->
view.updateLayoutParams {
(this as? ViewGroup.MarginLayoutParams)?.let {
updateMargins(
left = initialLeft + (if (left) insets.systemWindowInsetLeft else 0),
top = initialTop + (if (top) insets.systemWindowInsetTop else 0),
right = initialRight + (if (right) insets.systemWindowInsetRight else 0),
bottom = initialBottom + (if (bottom) insets.systemWindowInsetBottom else 0)
)
}
}

insets
}
}
例如,只需调用 fab.addSystemWindowInsetToMargin(bottom = true) FAB 将向上移动到导航栏上方。或 app_bar.addSystemWindowInsetToPadding(top = true)将应用栏保持在状态栏下方(注意边距/填充差异)。

关于android - 使用 WindowInsets 在 Android 上正确进行边到边处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57293449/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com