board: the FAB and the undo snackbar rode behind the keyboard
Found by the Scaffold audit #2951 asked for. Three Scaffolds exist; the editor and the sync screen both consume the IME inset, and the board consumed nothing. `enableEdgeToEdge()` makes the manifest's `adjustResize` a no-op on API 30+, so nothing resizes for the keyboard unless the app asks — and `ScaffoldDefaults.contentWindowInsets` is systemBars, which the IME is not part of. The Scaffold positions the FAB and the snackbar host from that value, so with the search field focused both sat under the keyboard. Not theoretical, and newly load-bearing: `3f0eef1` put an UNDO on the trash snackbar, so the one control you could not reach was the one that takes back a note you did not mean to throw away — reachable by searching, long-pressing a hit and trashing it. `union` rather than `add`: the navigation bar and the IME are the same edge, not two stacked ones, and adding them would inset twice under a keyboard that already covers the nav bar. Set once on the Scaffold rather than per-slot, so the content column shrinks with it and the board's cards stay above the keyboard instead of scrolling under it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,11 +6,14 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.ime
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.union
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
|
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
|
||||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
||||||
@@ -37,6 +40,7 @@ import androidx.compose.material3.ModalDrawerSheet
|
|||||||
import androidx.compose.material3.ModalNavigationDrawer
|
import androidx.compose.material3.ModalNavigationDrawer
|
||||||
import androidx.compose.material3.NavigationDrawerItem
|
import androidx.compose.material3.NavigationDrawerItem
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.ScaffoldDefaults
|
||||||
import androidx.compose.material3.SnackbarDuration
|
import androidx.compose.material3.SnackbarDuration
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
@@ -138,6 +142,21 @@ fun BoardScreen(
|
|||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
// The IME, added to what the Scaffold already insets for. `enableEdgeToEdge`
|
||||||
|
// makes the manifest's `adjustResize` a no-op on API 30+, so nothing resizes
|
||||||
|
// for the keyboard unless the app asks — and `ScaffoldDefaults.contentWindowInsets`
|
||||||
|
// is systemBars, which the IME is not part of. The Scaffold positions the FAB
|
||||||
|
// AND the snackbar host from this value, so without it both sit behind the
|
||||||
|
// keyboard whenever the search field has focus. That is not theoretical: the
|
||||||
|
// undo on a trashed search hit is exactly the control you cannot reach.
|
||||||
|
//
|
||||||
|
// `union` rather than `add` — the two are the same edge, not two stacked ones.
|
||||||
|
// Adding them would inset by the navigation bar a second time underneath a
|
||||||
|
// keyboard that already covers it.
|
||||||
|
//
|
||||||
|
// One owner for the edge, as with the search bar's missing statusBarsPadding:
|
||||||
|
// set here, the content Column gets it through `padding` and must not repeat it.
|
||||||
|
contentWindowInsets = ScaffoldDefaults.contentWindowInsets.union(WindowInsets.ime),
|
||||||
snackbarHost = { SnackbarHost(snackbars) },
|
snackbarHost = { SnackbarHost(snackbars) },
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
// The + is the ONLY way in, by design: one obvious target rather
|
// The + is the ONLY way in, by design: one obvious target rather
|
||||||
|
|||||||
Reference in New Issue
Block a user