Devices/Android versions reproduced on: Android 5.0 Lollipop
I have an Activity that holds four Fragments via ViewPager2 and FragmentStateAdapter. I noticed that ViewCompat.setOnApplyWindowInsetsListener and its OnApplyWindowInsetsListener callback only fires one time at the first tab Fragment in Android 5 or probably all version prior to Android 15.
Activity - OnApplyWindowInsetsListener gets called
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.isNavigationBarContrastEnforced = false
}
super.onCreate(savedInstanceState)
setContent {... }
// Handling of insets for edge-to-edge enforcement
ViewCompat.setOnApplyWindowInsetsListener(root) { _: View, insets: WindowInsetsCompat ->
val barInset = insets.getInsets(WindowInsetsCompat.Type.systemBars())
// Add padding to this view based on status bar inset
toolbar.updatePadding(top = barInset.top)
// Return WindowInsetsCompat.CONSUMED if you don't want the window insets to keep passing down
// to descendant views including all views of Fragment(s) under this Activity
insets
}
val fragmentList = mutableListOf<Pair<String, Fragment>>(
Pair(getString(R.string.overview), OverviewFragment.newInstance()),
Pair(getString(R.string.profile), ProfileFragment.newInstance()),
Pair(getString(R.string.exchange), ExchangeFragment.newInstance()),
Pair(getString(R.string.metrics), MetricsFragment.newInstance())
)
val adapter = FragmentAdapter(fragmentList, this@AssetDetailActivity)
viewPager.adapter = adapter
// Retain every offscreen Fragments since its ViewModel is being cleared after configuration change if not visible on the screen
viewPager.offscreenPageLimit = fragmentList.size.minus(1)
viewPager.isUserInputEnabled = false
}
OverviewFragment - OnApplyWindowInsetsListener gets called
// Handling of insets for edge-to-edge enforcement
ViewCompat.setOnApplyWindowInsetsListener(root) { _: View, insets: WindowInsetsCompat ->
val barInset = insets.getInsets(WindowInsetsCompat.Type.systemBars())
// Add padding to this view based on navigation bar inset
parentScrollView.updatePadding(bottom = barInset.bottom)
parentScrollView.clipToPadding = false
// Return WindowInsetsCompat.CONSUMED if you don't want the window insets to keep passing down
// to descendant views including all views of Fragment(s) under this Fragment
WindowInsetsCompat.CONSUMED
}
ProfileFragment - OnApplyWindowInsetsListener gets called for Android 15 but not on Android 5
// Handling of insets for edge-to-edge enforcement
ViewCompat.setOnApplyWindowInsetsListener(root) { _: View, insets: WindowInsetsCompat ->
val barInset = insets.getInsets(WindowInsetsCompat.Type.systemBars())
// Add padding to this view based on navigation bar inset
parentScrollView.updatePadding(bottom = barInset.bottom)
parentScrollView.clipToPadding = false
// Return WindowInsetsCompat.CONSUMED if you don't want the window insets to keep passing down
// to descendant views including all views of Fragment(s) under this Fragment
WindowInsetsCompat.CONSUMED
}
ExchangeFragment - OnApplyWindowInsetsListener gets called for Android 15 but not on Android 5
// Handling of insets for edge-to-edge enforcement
ViewCompat.setOnApplyWindowInsetsListener(root) { _: View, insets: WindowInsetsCompat ->
val barInset = insets.getInsets(WindowInsetsCompat.Type.systemBars())
// Add padding to this view based on navigation bar inset
parentScrollView.updatePadding(bottom = barInset.bottom)
parentScrollView.clipToPadding = false
// Return WindowInsetsCompat.CONSUMED if you don't want the window insets to keep passing down
// to descendant views including all views of Fragment(s) under this Fragment
WindowInsetsCompat.CONSUMED
}
MetricsFragment - OnApplyWindowInsetsListener gets called for Android 15 but not on Android 5
// Handling of insets for edge-to-edge enforcement
ViewCompat.setOnApplyWindowInsetsListener(root) { _: View, insets: WindowInsetsCompat ->
val barInset = insets.getInsets(WindowInsetsCompat.Type.systemBars())
// Add padding to this view based on navigation bar inset
parentScrollView.updatePadding(bottom = barInset.bottom)
parentScrollView.clipToPadding = false
// Return WindowInsetsCompat.CONSUMED if you don't want the window insets to keep passing down
// to descendant views including all views of Fragment(s) under this Fragment
WindowInsetsCompat.CONSUMED
}
Also worth mentioning that when using other Android's tab solution such as Material Design Component BottomNavigationView with Jetpack Navigation, returning WindowInsetsCompat.CONSUMED on each Fragments does not end the passing of window insets regardless of Android version I am running. So I don't know if this is a bug for backward compatibility of edge-to-edge enforcement, it seems that ViewPager Fragments view hierarchy are treated as one in older devices?
Description
Component used: Activity
Version used:
1.9.3
Devices/Android versions reproduced on: Android 5.0 Lollipop
I have an Activity that holds four Fragments via
ViewPager2
andFragmentStateAdapter
. I noticed thatViewCompat.setOnApplyWindowInsetsListener
and itsOnApplyWindowInsetsListener
callback only fires one time at the first tab Fragment in Android 5 or probably all version prior to Android 15.Activity -
OnApplyWindowInsetsListener
gets calledOverviewFragment -
OnApplyWindowInsetsListener
gets calledProfileFragment -
OnApplyWindowInsetsListener
gets called for Android 15 but not on Android 5ExchangeFragment -
OnApplyWindowInsetsListener
gets called for Android 15 but not on Android 5MetricsFragment -
OnApplyWindowInsetsListener
gets called for Android 15 but not on Android 5Also worth mentioning that when using other Android's tab solution such as Material Design Component
BottomNavigationView
with Jetpack Navigation, returningWindowInsetsCompat.CONSUMED
on each Fragments does not end the passing of window insets regardless of Android version I am running. So I don't know if this is a bug for backward compatibility of edge-to-edge enforcement, it seems thatViewPager
Fragments view hierarchy are treated as one in older devices?