← Back to garden 🤏

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)
        }
    }
}