ScreenScaffold
Composable Component
ScreenScaffold
is one of the Wear Material3 scaffold components.
Android
@Composable
public fun ScreenScaffold(
scrollState: ScalingLazyListState,
edgeButton: @Composable BoxScope.() -> Unit,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = { ScrollIndicator(scrollState) },
edgeButtonSpacing: Dp = ScreenScaffoldDefaults.EdgeButtonSpacing,
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
content: @Composable BoxScope.(PaddingValues) -> Unit,
): Unit
Parameters
scrollState | The scroll state for ScalingLazyColumn , used to drive screen transitions such as TimeText scroll away and showing/hiding ScrollIndicator . |
edgeButton | Slot for an EdgeButton that takes the available space below a scrolling list. It will scale up and fade in when the user scrolls to the end of the list, and scale down and fade out as the user scrolls up. |
modifier | The modifier for the screen scaffold. |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. The bottom padding value is always ignored because we instead use edgeButtonSpacing to specify the gap between edge button and content - and the EdgeButton hugs the bottom of the screen. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
edgeButtonSpacing | The space between EdgeButton and the list content |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as edgeButton and scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists to properly offset the EdgeButton . |
Android
@Composable
public fun ScreenScaffold(
scrollState: ScalingLazyListState,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = { ScrollIndicator(scrollState) },
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
content: @Composable BoxScope.(PaddingValues) -> Unit,
): Unit
Parameters
scrollState | The scroll state for ScalingLazyColumn , used to drive screen transitions such as TimeText scroll away and showing/hiding ScrollIndicator . |
modifier | The modifier for the screen scaffold. |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists to properly offset the EdgeButton . |
Android
@Composable
public fun ScreenScaffold(
scrollState: TransformingLazyColumnState,
edgeButton: @Composable BoxScope.() -> Unit,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = { ScrollIndicator(scrollState) },
edgeButtonSpacing: Dp = ScreenScaffoldDefaults.EdgeButtonSpacing,
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
content: @Composable BoxScope.(PaddingValues) -> Unit,
): Unit
Parameters
scrollState | The scroll state for TransformingLazyColumn , used to drive screen transitions such as TimeText scroll away and showing/hiding ScrollIndicator . |
edgeButton | Slot for an EdgeButton that takes the available space below a scrolling list. It will scale up and fade in when the user scrolls to the end of the list, and scale down and fade out as the user scrolls up. |
modifier | The modifier for the screen scaffold. |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. The bottom padding value is always ignored because we instead use edgeButtonSpacing to specify the gap between edge button and content - and the EdgeButton hugs the bottom of the screen. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
edgeButtonSpacing | The space between EdgeButton and the list content |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as edgeButton and scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists to properly offset the EdgeButton . |
Android
@Composable
public fun ScreenScaffold(
scrollState: TransformingLazyColumnState,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = { ScrollIndicator(scrollState) },
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
content: @Composable BoxScope.(PaddingValues) -> Unit,
): Unit
Parameters
scrollState | The scroll state for TransformingLazyColumn , used to drive screen transitions such as TimeText scroll away and showing/hiding ScrollIndicator . |
modifier | The modifier for the screen scaffold. |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists. |
Android
@Composable
public fun ScreenScaffold(
scrollState: LazyListState,
edgeButton: @Composable BoxScope.() -> Unit,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = { ScrollIndicator(scrollState) },
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
edgeButtonSpacing: Dp = ScreenScaffoldDefaults.EdgeButtonSpacing,
content: @Composable BoxScope.(PaddingValues) -> Unit,
): Unit
Parameters
scrollState | The scroll state for androidx.compose.foundation.lazy.LazyColumn , used to drive screen transitions such as TimeText scroll away and showing/hiding ScrollIndicator . |
edgeButton | Slot for an EdgeButton that takes the available space below a scrolling list. It will scale up and fade in when the user scrolls to the end of the list, and scale down and fade out as the user scrolls up. |
modifier | The modifier for the screen scaffold. |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. The bottom padding value is always ignored because we instead use edgeButtonSpacing to specify the gap between edge button and content - and the EdgeButton hugs the bottom of the screen. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
edgeButtonSpacing | The space between EdgeButton and the list content |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as edgeButton and scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists to properly offset the EdgeButton . |
Android
@Composable
public fun ScreenScaffold(
scrollState: LazyListState,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = { ScrollIndicator(scrollState) },
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
content: @Composable BoxScope.(PaddingValues) -> Unit,
): Unit
Parameters
scrollState | The scroll state for androidx.compose.foundation.lazy.LazyColumn , used to drive screen transitions such as TimeText scroll away and showing/hiding ScrollIndicator . |
modifier | The modifier for the screen scaffold. |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists. |
Android
@Composable
public fun ScreenScaffold(
scrollState: ScrollState,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = { ScrollIndicator(scrollState) },
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
content: @Composable BoxScope.(PaddingValues) -> Unit,
): Unit
Parameters
scrollState | The scroll state for a Column, used to drive screen transitions such as TimeText scroll away and showing/hiding ScrollIndicator . |
modifier | The modifier for the screen scaffold. |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists. |
Android
@Composable
public fun ScreenScaffold(
scrollInfoProvider: ScrollInfoProvider,
edgeButton: @Composable BoxScope.() -> Unit,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = null,
edgeButtonSpacing: Dp = ScreenScaffoldDefaults.EdgeButtonSpacing,
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
content: @Composable BoxScope.(PaddingValues) -> Unit,
)
Parameters
scrollInfoProvider | Provider for scroll information used to scroll away screen elements such as TimeText and coordinate showing/hiding the ScrollIndicator , this needs to be a ScrollInfoProvider . |
edgeButton | slot for a EdgeButton that takes the available space below a scrolling list. It will scale up and fade in when the user scrolls to the end of the list, and scale down and fade out as the user scrolls up. |
modifier | The modifier for the screen scaffold. |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. The bottom padding value is always ignored because we instead use edgeButtonSpacing to specify the gap between edge button and content - and the EdgeButton hugs the bottom of the screen. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
edgeButtonSpacing | The space between EdgeButton and the list content. This gap size could not be smaller then ScreenScaffoldDefaults.EdgeButtonMinSpacing . |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as edgeButton and scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists to properly offset the EdgeButton . |
Android
@Composable
public fun ScreenScaffold(
modifier: Modifier = Modifier,
scrollInfoProvider: ScrollInfoProvider? = null,
contentPadding: PaddingValues = ScreenScaffoldDefaults.contentPadding,
timeText: (@Composable () -> Unit)? = null,
scrollIndicator: (@Composable BoxScope.() -> Unit)? = null,
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
content: @Composable BoxScope.(PaddingValues) -> Unit,
): Unit
Parameters
modifier | The modifier for the screen scaffold. |
scrollInfoProvider | Provider for scroll information used to scroll away screen elements such as TimeText and coordinate showing/hiding the ScrollIndicator . |
contentPadding | The padding to apply around the entire content. This contentPadding is then received by the content and should be consumed by using Modifier.padding or contentPadding parameter of the lazy lists. |
timeText | Time text (both time and potentially status message) for this screen, if different to the time text at the AppScaffold level. When null, the time text from the AppScaffold is displayed for this screen. |
scrollIndicator | The ScrollIndicator to display on this screen, which is expected to be aligned to Center-End. It is recommended to use the Material3 ScrollIndicator which is provided by default. No scroll indicator is displayed if null is passed. |
overscrollEffect | the OverscrollEffect that will be used to render overscroll for this layout. This overscroll effect will be shared with all components within this ScreenScaffold such as scrollIndicator through LocalOverscrollFactory . If necessary, this behaviour can be disabled by passing overscrollEffect = null. |
content | The body content for this screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding or contentPadding parameter when used with lists. |
Code Examples
EdgeButtonListSample
@Preview
@Composable
fun EdgeButtonListSample() {
val state = rememberScalingLazyListState()
val horizontalPadding = LocalConfiguration.current.screenWidthDp.dp * 0.052f
val verticalPadding = LocalConfiguration.current.screenHeightDp.dp * 0.16f
val colors =
listOf(
"Filled" to ButtonDefaults.buttonColors(),
"Filled Variant" to ButtonDefaults.filledVariantButtonColors(),
"Filled Tonal" to ButtonDefaults.filledTonalButtonColors(),
"Outlined" to ButtonDefaults.outlinedButtonColors(),
"Disabled" to ButtonDefaults.buttonColors(),
)
var selectedColor by remember { mutableIntStateOf(0) }
val types = listOf("Icon only" to 0, "Text only" to 1)
var selectedType by remember { mutableIntStateOf(0) }
ScreenScaffold(
scrollState = state,
contentPadding = PaddingValues(horizontal = horizontalPadding, vertical = verticalPadding),
edgeButton = {
EdgeButton(
modifier =
Modifier.scrollable(
state,
orientation = Orientation.Vertical,
reverseDirection = true,
// An overscroll effect should be applied to the EdgeButton for proper
// scrolling behavior.
overscrollEffect = rememberOverscrollEffect(),
),
onClick = {},
buttonSize = EdgeButtonSize.Medium,
colors = colors[selectedColor].second,
border =
if (colors[selectedColor].first == "Outlined")
ButtonDefaults.outlinedButtonBorder(true)
else null,
enabled = colors[selectedColor].first != "Disabled",
) {
if (selectedType == 0) {
// Remove extra spacing around the icon so it integrates better into the scroll.
CheckIcon(Modifier.size(21.dp).wrapContentSize(unbounded = true).size(32.dp))
} else {
Text("Ok")
}
}
},
) { contentPadding ->
ScalingLazyColumn(
state = state,
modifier = Modifier.fillMaxSize().selectableGroup(),
autoCentering = null,
contentPadding = contentPadding,
horizontalAlignment = Alignment.CenterHorizontally,
) {
item { Text("Color") }
items(colors.size) { ix ->
RadioButton(
label = { Text(colors[ix].first) },
selected = selectedColor == ix,
onSelect = { selectedColor = ix },
modifier = Modifier.fillMaxWidth(),
)
}
item { Text("Type") }
items(types.size) { ix ->
RadioButton(
label = { Text(types[ix].first) },
selected = selectedType == ix,
onSelect = { selectedType = ix },
modifier = Modifier.fillMaxWidth(),
)
}
}
}
}
ScaffoldSample
@Preview
@Composable
fun ScaffoldSample() {
// Declare just one [AppScaffold] per app such as in the activity.
// [AppScaffold] allows static screen elements (i.e. [TimeText]) to remain visible
// during in-app transitions such as swipe-to-dismiss.
AppScaffold {
// Define the navigation hierarchy within the AppScaffold,
// such as using SwipeDismissableNavHost.
// For this sample, we will define a single screen inline.
val listState = rememberScalingLazyListState()
// By default, ScreenScaffold will handle transitions showing/hiding ScrollIndicator,
// showing/hiding/scrolling away TimeText and optionally hosting the EdgeButton.
ScreenScaffold(scrollState = listState, contentPadding = PaddingValues(10.dp)) {
contentPadding ->
ScalingLazyColumn(
state = listState,
contentPadding = contentPadding,
modifier = Modifier.fillMaxSize(),
) {
items(10) { Button(onClick = {}, label = { Text("Item ${it + 1}") }) }
}
}
}
}
ScaffoldWithSLCEdgeButtonSample
@Preview
@Composable
fun ScaffoldWithSLCEdgeButtonSample() {
// Declare just one [AppScaffold] per app such as in the activity.
// [AppScaffold] allows static screen elements (i.e. [TimeText]) to remain visible
// during in-app transitions such as swipe-to-dismiss.
AppScaffold(modifier = Modifier.background(Color.Black)) {
// Define the navigation hierarchy within the AppScaffold,
// such as using SwipeDismissableNavHost.
// For this sample, we will define a single screen inline.
val listState = rememberScalingLazyListState()
// By default, ScreenScaffold will handle transitions showing/hiding ScrollIndicator,
// showing/hiding/scrolling away TimeText and optionally hosting the EdgeButton.
ScreenScaffold(
scrollState = listState,
// Define custom spacing between [EdgeButton] and [ScalingLazyColumn].
edgeButtonSpacing = 15.dp,
edgeButton = {
EdgeButton(
onClick = {},
modifier =
// In case user starts scrolling from the EdgeButton.
Modifier.scrollable(
listState,
orientation = Orientation.Vertical,
reverseDirection = true,
// An overscroll effect should be applied to the EdgeButton for proper
// scrolling behavior.
overscrollEffect = rememberOverscrollEffect(),
),
) {
Text("Clear All")
}
},
) { contentPadding ->
ScalingLazyColumn(
state = listState,
modifier = Modifier.fillMaxSize(),
// Bottom spacing is derived from [ScreenScaffold.edgeButtonSpacing].
contentPadding = contentPadding,
autoCentering = null,
) {
items(10) { Button(onClick = {}, label = { Text("Item ${it + 1}") }) }
}
}
}
}
ScaffoldWithTLCEdgeButtonSample
@Preview
@Composable
fun ScaffoldWithTLCEdgeButtonSample() {
// Declare just one [AppScaffold] per app such as in the activity.
// [AppScaffold] allows static screen elements (i.e. [TimeText]) to remain visible
// during in-app transitions such as swipe-to-dismiss.
AppScaffold(modifier = Modifier.background(Color.Black)) {
// Define the navigation hierarchy within the AppScaffold,
// such as using SwipeDismissableNavHost.
// For this sample, we will define a single screen inline.
val listState = rememberTransformingLazyColumnState()
// By default, ScreenScaffold will handle transitions showing/hiding ScrollIndicator,
// showing/hiding/scrolling away TimeText and optionally hosting the EdgeButton.
ScreenScaffold(
scrollState = listState,
// Define custom spacing between [EdgeButton] and [ScalingLazyColumn].
edgeButtonSpacing = 15.dp,
edgeButton = {
EdgeButton(
onClick = {},
modifier =
// In case user starts scrolling from the EdgeButton.
Modifier.scrollable(
listState,
orientation = Orientation.Vertical,
reverseDirection = true,
// An overscroll effect should be applied to the EdgeButton for proper
// scrolling behavior.
overscrollEffect = rememberOverscrollEffect(),
),
) {
Text("Clear All")
}
},
) { contentPadding ->
TransformingLazyColumn(
state = listState,
modifier = Modifier.fillMaxSize(),
// Bottom spacing is derived from [ScreenScaffold.edgeButtonSpacing].
contentPadding = contentPadding,
) {
items(10) { Button(onClick = {}, label = { Text("Item ${it + 1}") }) }
}
}
}
}
Create your own Component Library
Material Components are meant to be used as is and they do not allow customizations. To build your own Jetpack Compose component library use Compose Unstyled