diff --git a/components/src/main/kotlin/de/jeanlucmakiola/floret/components/CollapsingScaffold.kt b/components/src/main/kotlin/de/jeanlucmakiola/floret/components/CollapsingScaffold.kt index 65ee50d..e6b4d3c 100644 --- a/components/src/main/kotlin/de/jeanlucmakiola/floret/components/CollapsingScaffold.kt +++ b/components/src/main/kotlin/de/jeanlucmakiola/floret/components/CollapsingScaffold.kt @@ -46,6 +46,16 @@ import de.jeanlucmakiola.floret.identity.predictiveBack * unchanged: [actions] adds trailing app-bar items; [snackbarHost] hosts * transient messages; [predictiveBack] (off by default) wires the gesture * preview to [onBack] for full-screen surfaces that want it. + * + * Set [scrollable] to false when [content] brings its own scrolling container. + * The default column scrolls as a whole, which composes every row up front — + * fine for the short lists these surfaces normally hold, but a list long enough + * to need a [androidx.compose.foundation.lazy.LazyColumn] can neither nest one + * inside it (same-axis scrolling throws) nor afford the eager pass. Opting out + * hands [content] a plain, unscrolled column to fill instead; the insets, IME + * padding and bar behaviour are unchanged, so a lazy list simply takes over the + * scrolling and gets the top bar's collapse for free through the shared + * nested-scroll connection. */ @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -55,6 +65,7 @@ fun CollapsingScaffold( modifier: Modifier = Modifier, largeTopBar: Boolean = true, predictiveBack: Boolean = false, + scrollable: Boolean = true, actions: @Composable RowScope.() -> Unit = {}, snackbarHost: @Composable () -> Unit = {}, content: @Composable ColumnScope.() -> Unit, @@ -112,8 +123,19 @@ fun CollapsingScaffold( .fillMaxSize() .background(MaterialTheme.colorScheme.surface) .imePadding() - .verticalScroll(rememberScrollState()) - .padding(top = 8.dp, bottom = 24.dp), + .then( + if (scrollable) { + Modifier + .verticalScroll(rememberScrollState()) + .padding(top = 8.dp, bottom = 24.dp) + } else { + // The content scrolls itself, so it also owns the edge + // spacing — a lazy list wants it as contentPadding, or + // the first and last rows clip instead of scrolling + // under the bars. + Modifier + }, + ), content = content, ) } diff --git a/components/src/main/kotlin/de/jeanlucmakiola/floret/components/OptionPicker.kt b/components/src/main/kotlin/de/jeanlucmakiola/floret/components/OptionPicker.kt index c22afa1..ce929b0 100644 --- a/components/src/main/kotlin/de/jeanlucmakiola/floret/components/OptionPicker.kt +++ b/components/src/main/kotlin/de/jeanlucmakiola/floret/components/OptionPicker.kt @@ -20,12 +20,17 @@ import androidx.compose.ui.window.DialogWindowProvider * width without a tall header — it's a short selection list, so the large * collapsing header would only be empty space to scroll past. [content] places * the connected grouped rows; selecting one calls [onDismiss]. + * + * [scrollable] forwards to [CollapsingScaffold]: leave it on unless [content] + * scrolls itself, which a picker only needs for an option list long enough to + * warrant a lazy container. */ @Composable fun FullScreenPicker( title: String, onDismiss: () -> Unit, predictiveBack: Boolean = false, + scrollable: Boolean = true, actions: @Composable RowScope.() -> Unit = {}, content: @Composable ColumnScope.() -> Unit, ) { @@ -50,6 +55,7 @@ fun FullScreenPicker( onBack = onDismiss, largeTopBar = false, predictiveBack = predictiveBack, + scrollable = scrollable, actions = actions, content = content, )