WindowInsets — Listeners to layouts

Moving where we handle insets to where our views live, layout files

Chris Banes
Apr 12 · 6 min read

Drawing behind the navigation bar

<BottomNavigationView
    android:layout_height="wrap_content"
    android:layout_width="match_parent" />
rootView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
    <!-- Set the navigation bar to 50% translucent white -->
    <item name="android:navigationBarColor">#80FFFFFF</item>
    <!-- Since the nav bar is white, we will use dark icons -->
    <item name="android:windowLightNavigationBar">true</item>
</style>
The view is being displayed behind the navigation bar

Handling insets through padding

bottomNav.setOnApplyWindowInsetsListener { view, insets ->
    view.updatePadding(bottom = insets.systemWindowInsetBottom)
    insets
}
The view now has bottom padding which matches the navigation bar size
<BottomNavigationView
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:paddingVertical="24dp" />
The view has the correct top padding, but the intended bottom padding isn’t there
bottomNav.setOnApplyWindowInsetsListener { view, insets ->
  view.updatePadding(
    bottom = view.paddingBottom + insets.systemWindowInsetsBottom
  )
  insets
}
The accumulated padding after 3 WindowInset dispatches
// Keep a record of the intended bottom padding of the view
val bottomNavBottomPadding = bottomNav.paddingBottom

bottomNav.setOnApplyWindowInsetsListener { view, insets ->
  // We've got some insets, set the bottom padding to be the
  // original value + the inset value
  view.updatePadding(
    bottom = bottomNavBottomPadding + insets.systemWindowInsetBottom
  )
  insets
}
Finally, what we intended

doOnApplyWindowInsets

bottomNav.doOnApplyWindowInsets { view, insets, padding ->
    // padding contains the original padding values after inflation
    view.updatePadding(
        bottom = padding.bottom + insets.systemWindowInsetBottom
    )
}

requestApplyInsetsWhenAttached()

Wrapping it up in a bind

<BottomNavigationView
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:paddingVertical="24dp"
    app:paddingBottomSystemWindowInsets="@{ true }" />
<BottomNavigationView
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:paddingVertical="24dp"
    app:paddingBottomSystemWindowInsets="@{ true }"
    app:paddingLeftSystemWindowInsets="@{ true }" />

android:fitSystemWindows

Ergonomics FTW

Android Developers

The official Android Developers publication on Medium

Chris Banes

Written by

Work @Google on #Android

Android Developers

The official Android Developers publication on Medium