fix(edit): pin the picker title instead of a large collapsing header
Full-screen selection pickers opened with the LargeTopAppBar expanded, so the title started below the bar and only settled into it after a scroll — a tall empty header above a short option list. Give CollapsingScaffold a largeTopBar flag and have FullScreenPicker use a pinned single-line TopAppBar, so every picker (calendar, theme, week start, language, reminder, agenda range) shows its title in the bar from the start. Settings and the calendar manager keep the large collapsing header. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -57,10 +58,16 @@ fun positionOf(index: Int, count: Int): Position = when {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The app's standard full-screen list scaffold: a collapsing [LargeTopAppBar]
|
* The app's standard full-screen list scaffold. By default a collapsing
|
||||||
* whose title shrinks into the bar (next to the back button) as the content
|
* [LargeTopAppBar] whose title shrinks into the bar (next to the back button) as
|
||||||
* scrolls. Content is a scrollable column that feeds the toolbar via nested
|
* the content scrolls — used by Settings and the calendar manager, where the
|
||||||
* scroll. Used by Settings and the calendar manager so they share one shell.
|
* large header sets the page. Content is a scrollable column that feeds the
|
||||||
|
* toolbar via nested scroll.
|
||||||
|
*
|
||||||
|
* Set [largeTopBar] to false for a pinned, single-line [TopAppBar] instead: the
|
||||||
|
* title sits in the bar from the start, with no expanded header to scroll past.
|
||||||
|
* Preferred for selection pickers, where the tall header is just wasted space
|
||||||
|
* above the options.
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -68,12 +75,16 @@ fun CollapsingScaffold(
|
|||||||
title: String,
|
title: String,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
largeTopBar: Boolean = true,
|
||||||
snackbarHost: @Composable () -> Unit = {},
|
snackbarHost: @Composable () -> Unit = {},
|
||||||
actions: @Composable RowScope.() -> Unit = {},
|
actions: @Composable RowScope.() -> Unit = {},
|
||||||
content: @Composable ColumnScope.() -> Unit,
|
content: @Composable ColumnScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
val scrollBehavior =
|
val scrollBehavior = if (largeTopBar) {
|
||||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
|
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
|
||||||
|
} else {
|
||||||
|
TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||||
|
}
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.predictiveBack(onBack = onBack)
|
.predictiveBack(onBack = onBack)
|
||||||
@@ -81,22 +92,34 @@ fun CollapsingScaffold(
|
|||||||
.background(MaterialTheme.colorScheme.surface)
|
.background(MaterialTheme.colorScheme.surface)
|
||||||
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
LargeTopAppBar(
|
val navigationIcon = @Composable {
|
||||||
title = { Text(title) },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBack) {
|
IconButton(onClick = onBack) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.AutoMirrored.Filled.ArrowBack,
|
Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
contentDescription = stringResource(R.string.settings_back),
|
contentDescription = stringResource(R.string.settings_back),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
val colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
scrolledContainerColor = MaterialTheme.colorScheme.surface,
|
||||||
|
)
|
||||||
|
if (largeTopBar) {
|
||||||
|
LargeTopAppBar(
|
||||||
|
title = { Text(title) },
|
||||||
|
navigationIcon = navigationIcon,
|
||||||
actions = actions,
|
actions = actions,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
colors = colors,
|
||||||
scrolledContainerColor = MaterialTheme.colorScheme.surface,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
TopAppBar(
|
||||||
|
title = { Text(title) },
|
||||||
|
navigationIcon = navigationIcon,
|
||||||
|
actions = actions,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
colors = colors,
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
snackbarHost = snackbarHost,
|
snackbarHost = snackbarHost,
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ import de.jeanlucmakiola.calendula.ui.agenda.AgendaRange
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared full-screen scaffold for selection pickers: a full-bleed [Dialog] that
|
* Shared full-screen scaffold for selection pickers: a full-bleed [Dialog] that
|
||||||
* reuses the app's [CollapsingScaffold] (collapsing title + back button), so a
|
* reuses the app's [CollapsingScaffold] (back button + full width), but with a
|
||||||
* picker is visually identical to a Settings sub-page and uses the full width.
|
* pinned single-line title rather than the large collapsing header — a picker is
|
||||||
|
* a short list, so the tall header would only be empty space to scroll past.
|
||||||
* [content] places the connected grouped rows; selecting one calls [onDismiss].
|
* [content] places the connected grouped rows; selecting one calls [onDismiss].
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
@@ -69,7 +70,12 @@ fun FullScreenPicker(
|
|||||||
(view.parent as? DialogWindowProvider)?.window
|
(view.parent as? DialogWindowProvider)?.window
|
||||||
?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
||||||
}
|
}
|
||||||
CollapsingScaffold(title = title, onBack = onDismiss, content = content)
|
CollapsingScaffold(
|
||||||
|
title = title,
|
||||||
|
onBack = onDismiss,
|
||||||
|
largeTopBar = false,
|
||||||
|
content = content,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user