setOnApplyWindowInsetsListener从未调用

时间:2019-01-06 15:07:57

标签: android user-interface

我想计算NavigationBar的高度。我看过这个演示文稿:https://chris.banes.me/talks/2017/becoming-a-master-window-fitter-nyc/

因此,我尝试使用方法View.setOnApplyWindowInsetsListener()。 但是,由于某种原因,它从未被调用。

有人知道为什么吗?有什么限制吗?

我试图这样使用它:

navBarOverlay.setOnApplyWindowInsetsListener { v, insets -> 
   Timber.i("BOTTOM = ${insets.systemWindowInsetBottom}")
   return@setOnApplyWindowInsetsListener insets
}

请注意,我的根目录布局是ConstraintLayout

11 个答案:

答案 0 :(得分:0)

我不得不(而且我想应该)在某个适当的时间显式调用requestApplyInsets()来使监听器受到打击。

请查看本文以获取一些可能的提示:https://medium.com/androiddevelopers/windowinsets-listeners-to-layouts-8f9ccc8fa4d1

答案 1 :(得分:0)

在我的应用中,它只会被调用一次,而不是每次都被调用。因此,在一次调用中,我将widnowInsets保存到一个全局变量中,以在整个应用程序中使用它。

答案 2 :(得分:0)

我遇到了同样的问题。

如果您的根视图为ConstraintLayout且包含android:fitsSystemWindows =“ true” attr,则该视图使用onApplyWindowInsets回调。 因此,如果您在子视图上设置onApplyWindowInsets,则它们永远不会获得onApplyWindowInsets回调。

或者检查您的父视图是否使用了回调。

答案 3 :(得分:0)

我的解决方案是在navBarOverlay.rootView上调用它。

答案 4 :(得分:0)

这是我观察到的;换句话说,您的经历可能会有所不同。

[Layout for Activity]
<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:id="@+id/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"    <--
    tools:context=".MyAppActivity">

    ...

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

最外面的布局中的通知android:fitsSystemWindows="true"。只要有,setOnApplyWindowInsetsListener()就会被调用。

class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...

        ViewCompat.setOnApplyWindowInsetsListener(fab) { view, insets ->
            ...
            insets
        }
    }

或者,如果您要使用“全屏”,这意味着您希望将布局扩展到状态栏和导航栏,则可以执行以下操作。

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    WindowCompat.setDecorFitsSystemWindows(window, false)    <--

    ViewCompat.setOnApplyWindowInsetsListener(fab) { view, insets ->
        ...
        insets
    }
}

使用“片段”时,只要“活动”(包含片段)在最外面的布局中具有fitsSystemWindows或将“活动”设置为全屏显示,该思想同样适用。

答案 5 :(得分:0)

使用CollapsingToolbarLayout时遇到了这个问题,问题是CollapsingToolbarLayout不调用插入侦听器,如果您有CollapsingToolbarLayout,则此组件之后的所有其他视图插入不会被触发。如果是这样,请通过调用

CollapsingToolbarLayout中删除监听器
ViewCompat.setOnApplyWindowInsetsListener(collapsingToolbarLayout, null)

如果您不CollapsingToolbarLayout,那么其他一些视图会阻止插图在视图之间传递。

或者您已经食用了它们,我想您没有这样做)

答案 6 :(得分:0)

- willvincent/laravel-rateable[2.2.0, ..., 2.2.1] require illuminate/support ^6.0|^7.0 -> found illuminate/support[v6.0.0, ..., 6.x-dev, v7.0.0, ..., 7.x-dev] but it conflicts with another require. - Root composer.json requires willvincent/laravel-rateable ^2.2 -> satisfiable by willvincent/laravel-rateable[2.2.0, 2.2.1]. 中也存在一个错误,它阻止兄弟姐妹接收插图,您可以在issues github link中看到它。解决方案之一是将CollapsingToolbarLayout放在xml其他视图的下面,以便他们接收插图。

答案 7 :(得分:0)

我使用 this 答案使用了以下解决方案:

ViewCompat.setOnApplyWindowInsetsListener(
        findViewById(android.R.id.content)
    ) { _: View?, insets: WindowInsetsCompat ->
        navigationBarHeight = insets.systemWindowInsetBottom
        insets
    }

答案 8 :(得分:0)

ViewCompat.setOnApplyWindowInsetsListener 放入 onResume 对我使用了约束布局。

@Override
public void onResume() {
    super.onResume();
    ViewCompat.setOnApplyWindowInsetsListener(requireActivity().getWindow().getDecorView(), (v, insets) -> {
            boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
            int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
            return insets;
        });
} 

答案 9 :(得分:0)

我在 API 30 上遇到了类似的问题。 要使 setOnApplyWindowInsetsListener() 工作,您必须确保您的活动处于全屏模式。您可以使用以下方法来做到这一点

WindowCompat.setDecorFitsSystemWindows(activity.window, false) //this is backward compatible version

还要确保您没有在任何地方使用以下方法来设置 UI 标志

View.setSystemUiVisibility(int visibility)

答案 10 :(得分:0)

我在我的项目中使用了以下解决方案,它就像一个魅力。

val decorView: View = requireActivity().window.decorView
val rootView = decorView.findViewById<View>(android.R.id.content) as ViewGroup
ViewCompat.setOnApplyWindowInsetsListener(rootView) { _, insets ->
    val isKeyboardVisible = isKeyboardVisible(insets)
    Timber.d("isKeyboardVisible: $isKeyboardVisible")

    // Do something with isKeyboardVisible

    insets
}

private fun isKeyboardVisible(insets: WindowInsetsCompat): Boolean {
    val systemWindow = insets.systemWindowInsets
    val rootStable = insets.stableInsets
    if (systemWindow.bottom > rootStable.bottom) {
        // This handles the adjustResize case on < API 30, since
        // systemWindow.bottom is probably going to be the IME
        return true
    }
    return false
}

在 Android API 中使用 setWindowInsetsAnimationCallback 而不是 setOnApplyWindowInsetsListener > 30