Use the right insets in the home screen UI (#7271)

* Use the right insets in the home screen UI

That's `WindowInsets.statusBar` for the `Scaffold` component, then `WindowInsets.navigationBar` for the `LazyColum.contentPadding`

* Apply it to other screens with long lists of items too

* Apply the insets to `PreferencePage` too

* Apply inset changes to other screens with scrollable content

* Add helper insets/padding values based on review suggestions.

* Use the newly added insets/padding values in several scaffold and scrollable columns

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa
2026-07-27 18:17:14 +02:00
committed by GitHub
parent 0442fbd307
commit 77edfec61a
31 changed files with 208 additions and 73 deletions
@@ -10,13 +10,11 @@ package io.element.android.libraries.designsystem.components.preferences
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.plus
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -34,6 +32,8 @@ import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
@Composable
fun PreferencePage(
@@ -46,9 +46,8 @@ fun PreferencePage(
Scaffold(
modifier = modifier
.fillMaxSize()
.systemBarsPadding()
.imePadding(),
contentWindowInsets = WindowInsets.statusBars,
contentWindowInsets = scaffoldScrollableContentInsets,
topBar = {
PreferenceTopAppBar(
title = title,
@@ -56,12 +55,12 @@ fun PreferencePage(
)
},
snackbarHost = snackbarHost,
content = {
content = { contentPadding ->
Column(
modifier = Modifier
.padding(it)
.consumeWindowInsets(it)
.verticalScroll(state = rememberScrollState())
.padding(contentPadding + lazyColumnContentPadding)
.consumeWindowInsets(contentPadding + lazyColumnContentPadding)
) {
content()
}
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.designsystem.utils
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import io.element.android.libraries.designsystem.theme.components.Scaffold
/**
* Content insets meant to be used for [Column] or [LazyColumn] components that are used as the main content of a screen,
* to avoid overlapping with navigation bars, IME or cut-out display parts, but ignoring the status bar.
*
* Counterpart of [scaffoldScrollableContentInsets] for [Column] or [LazyColumn] components.
*/
val lazyColumnContentPadding @Composable
get() = WindowInsets.safeDrawing
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
.asPaddingValues()
/**
* Content insets meant to be used for [Scaffold] components that contain some content that is scrollable like [Column] or [LazyColumn],
* and this content should handle its own content padding. The insets will only apply the top padding to avoid overlapping with the status bar,
* while ignoring navigation bars, IME or cut-out display parts.
*
* Counterpart of [lazyColumnContentPadding] for [Scaffold] components.
*/
val scaffoldScrollableContentInsets @Composable
get() = WindowInsets.safeDrawing
.only(WindowInsetsSides.Top)
@@ -14,11 +14,14 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
@@ -67,6 +70,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.SegmentedButton
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.timeline.Timeline
@@ -125,6 +129,7 @@ fun MediaGalleryView(
},
)
},
contentWindowInsets = scaffoldScrollableContentInsets,
) { paddingValues ->
Column(
modifier = Modifier
@@ -320,6 +325,7 @@ private fun MediaGalleryFilesList(
val presenterFactories = LocalMediaItemPresenterFactories.current
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
) {
items(
items = files,
@@ -396,6 +402,7 @@ private fun MediaGalleryImageGrid(
columns = GridCells.Adaptive(80.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
) {
items(
items = imagesAndVideos,
@@ -53,6 +53,8 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.OnVisibleRangeChangeEffect
import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.ui.components.SelectedRoom
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
@@ -133,7 +135,8 @@ fun RoomSelectView(
)
}
)
}
},
contentWindowInsets = scaffoldScrollableContentInsets,
) { paddingValues ->
Column(
Modifier
@@ -149,7 +152,10 @@ fun RoomSelectView(
resultState = state.resultState,
showBackButton = false,
) { summaries ->
LazyColumn(state = lazyListState) {
LazyColumn(
state = lazyListState,
contentPadding = lazyColumnContentPadding,
) {
item {
SelectedRoomsHelper(
selectedRooms = state.selectedRooms,
@@ -11,14 +11,12 @@ package io.element.android.libraries.troubleshoot.impl.history
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
@@ -50,6 +48,7 @@ import io.element.android.libraries.designsystem.theme.components.ListItem
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets
import io.element.android.libraries.push.api.history.PushHistoryItem
import io.element.android.libraries.troubleshoot.impl.R
import io.element.android.libraries.ui.strings.CommonStrings
@@ -68,7 +67,7 @@ fun PushHistoryView(
.fillMaxSize()
.systemBarsPadding()
.imePadding(),
contentWindowInsets = WindowInsets.statusBars,
contentWindowInsets = scaffoldScrollableContentInsets,
topBar = {
TopAppBar(
navigationIcon = {