[ScreenScaffold] is one of the Wear Material3 scaffold components.
The scaffold components [AppScaffold] and [ScreenScaffold] lay out the structure of a screen and
coordinate transitions of the [ScrollIndicator] and [TimeText] components. [AppScaffold] should
be at the top of the composition (because it provides [ScaffoldState] and layers [TimeText] on
top of all other content) and [ScreenScaffold] should be part of [AppScaffold]'s content. When
used in conjunction with SwipeDismissableNavHost, [AppScaffold] remains at the top of the
composition, whilst [ScreenScaffold] will be placed for each individual composable route.
[ScreenScaffold] displays the [ScrollIndicator] at the center-end of the screen by default and
coordinates showing/hiding [TimeText] and [ScrollIndicator] according to [scrollState].
This version of [ScreenScaffold] has a special slot for a button at the bottom, that grows and
shrinks to take the available space after the scrollable content.
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. Note that the [OverscrollEffect.node] will be applied internally as well - you do not need to use Modifier.overscroll separately.
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].
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. Note that the [OverscrollEffect.node] will be applied internally as well - you do not need to use Modifier.overscroll separately.
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].
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. Note that the[OverscrollEffect.node] will be applied internally as well - you do not need to use Modifier.overscroll separately.
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].
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. Note that the [OverscrollEffect.node] will be applied internally as well - you do not need to use Modifier.overscroll separately.
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.
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. Note that the [OverscrollEffect.node] will be applied internally as well - you do not need to useModifier.overscroll separately.
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].
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. Note that the [OverscrollEffect.node] will be applied internally as well - you do not need to use Modifier.overscroll separately.
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.
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. Note that the [OverscrollEffect.node] will be applied internally as well - you do not need to use Modifier.overscroll separately.
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.
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. Note that the [OverscrollEffect.node] will be applied internally as well - you do not need to use Modifier.overscroll separately.
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].
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. Note that the [OverscrollEffect.node] will be applied internally as well - you do not need to use Modifier.overscroll separately.
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
ScaffoldWithEdgeButtonSample
@Preview@ComposablefunScaffoldWithEdgeButtonSample(){// 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 overscrollEffect =rememberOverscrollEffect()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, overscrollEffect = overscrollEffect,// 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, overscrollEffect = overscrollEffect
)){Text("Clear All")}},){ contentPadding ->ScalingLazyColumn( state = listState, modifier = Modifier.fillMaxSize(),// Don't consume overscroll effect inside [ScalingLazyColumn] since we want to apply// it to the scaffold itself. overscrollEffect = overscrollEffect?.withoutVisualEffect(),// Bottom spacing is derived from [ScreenScaffold.edgeButtonSpacing]. contentPadding = contentPadding,){items(10){Button( onClick ={}, label ={Text("Item ${it +1}")},)}}}}}
ScaffoldSample
@Preview@ComposablefunScaffoldSample(){// 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}")},)}}}}}
EdgeButtonListSample
@Preview@ComposablefunEdgeButtonListSample(){val state =rememberScalingLazyListState()val horizontalPadding = LocalConfiguration.current.screenWidthDp.dp *0.052fval verticalPadding = LocalConfiguration.current.screenHeightDp.dp *0.16fval 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"to0,"Text only"to1)var selectedType by remember {mutableIntStateOf(0)}ScreenScaffold( scrollState = state, contentPadding =PaddingValues(horizontal = horizontalPadding, vertical = verticalPadding), edgeButton ={EdgeButton( onClick ={}, buttonSize = EdgeButtonSize.Medium, colors = colors[selectedColor].second, border =if(colors[selectedColor].first =="Outlined") ButtonDefaults.outlinedButtonBorder(true)elsenull, 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())}}}}