output
Android 15 : Handle Edge-to-Edge Insets in XML
Description
When targeting Android 15, the system enforces your app to handle edge-to-edge content, mostly breaking items located on the extremes of the screen, this is specially painful in XML. Thankfully there is a way of making it a bit easier and less repetitive
Emulator setup
You can simulate a really tall cutout by going to developer options → Display cutout → Tall cutout in your emulator, this will allow you to spot UI issues easier. (id nothing happens, rotate the device)
Simple handling
XML Fit system windows
android:fitSystemWindows="true"
With Code
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())
view.updatePadding(
bottom = insets.bottom,
)
WindowInsetsCompat.CONSUMED
}
Helper function
fun View.applyEdgeToEdgeInsets(
typeMask: Int = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout(),
propagateInsets: Boolean = false,
scope: View.(Insets) -> Unit
) {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
val insets = windowInsets.getInsets(typeMask)
scope(view, insets)
if (propagateInsets) windowInsets else WindowInsetsCompat.CONSUMED
}
}
fun View.updateMargins(block: ViewGroup.MarginLayoutParams.() -> Unit) {
updateLayoutParams<ViewGroup.MarginLayoutParams> {
apply { block() }
}
}
enum class InsetType {
Margin,
Padding
}
fun View.applyBottomInsets(type: InsetType = InsetType.Margin) {
applyEdgeToEdgeInsets { insets ->
when(type) {
InsetType.Margin -> updateMargins { bottomMargin = insets.bottom }
InsetType.Padding -> updatePadding(bottom = insets.bottom)
}
}
}