Wear Compose M3
Android (Google)OfficialCreated by Google LLCDistributed by Android (Google)
- Skill
- Tool integration
- Software development
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides essential guidance for developers building or migrating Wear OS applications to the Material 3 (M3) design system. It covers the integration of androidx.wear.compose.material3, foundation, and navigation libraries, offering best practices for component usage, project migration from Material 2.5 or Horologist, and implementation of key Wear OS features like ambient mode and scaffold structures.
What it does
- Provides migration paths from Material 2.5 and Horologist to Wear Compose M3.
- Defines mandatory project configuration for Kotlin, Compose compiler, and SDK versions.
- Maps legacy components to their modern M3 equivalents.
- Offers a comprehensive reference table for canonical component samples.
- Guides developers on implementing scaffold structures and ambient mode.
- Enforces strict versioning and build validation protocols.
When to use it
- When starting a new Wear OS project using Compose Material 3.
- When migrating an existing Wear OS app from Material 2.5 or Horologist.
- When updating dependencies for Wear Compose libraries.
- When looking for canonical implementation samples for M3 components.
Advantages
- Ensures consistency with official Google Material 3 design standards.
- Reduces migration friction through clear component mapping.
- Promotes stable build practices by enforcing version compliance.
- Centralizes access to verified component samples and implementation patterns.
Usage examples
- “How do I migrate my Wear OS app from Material 2.5 to Material 3?”
- The agent will guide you through updating your dependencies, replacing legacy components like Chip with Button, and updating your MaterialTheme implementation to use ColorScheme and MotionScheme.
- “What is the M3 equivalent for ScalingLazyColumn?”
- The agent will advise using TransformingLazyColumn and provide links to the relevant samples for implementation.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/android/wear-compose-m3/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip wear-compose-m3.zip -d .agents/skills
Documentation by Google LLC
Prerequisites and compatibility
Current Wear OS Compose version in-use: To find the installed library version, read
gradle/libs.versions.tomlorbuild.gradle.ktsdirectly. Don't run./gradlew dependenciesor other shell commands to resolve versions.Wear OS Compose Material3 version: If an internal tool is available to establish the latest stable version
{VERSION}ofandroidx.wear.compose:compose-material3, use that tool.Otherwise, fetch the official Maven metadata XML to identify
{VERSION}(highest number, ignoring-alpha,-beta, or-rc).
Strict compliance: If a version is listed as stable, you MUST use it, unless overridden by the user. Do not downgrade based on initial "Unresolved reference" errors in the editor or outdated web search results.
Kotlin & Compose compiler: Use Kotlin 2.0.0+ with the
org.jetbrains.kotlin.plugin.composeGradle plugin.Min SDK: Ensure
minSdkis at least 25.Compile SDK & AGP: Ensure
compileSdkand AGP meet the library's AAR metadata floors (compileSdk >= 35andAGP >= 8.6.0for1.6.x;compileSdk >= 37andAGP >= 9.1.0for1.7.x).
Gotchas
Mandatory sync and validation: After updating versions in
libs.versions.tomlorbuild.gradle.kts, perform a Gradle sync (or./gradlew assembleDebug) before refactoring, and run./gradlew assembleDebugafter refactoring to verify the build.Prohibition of guessing (error protocol): If you encounter an 'Unresolved Reference' or API mismatch after a successful sync, do not attempt to 'fix' it by downgrading the library version.
Capabilities and tools
Capability 1: Migration, updates, and adding features
Use this guidance when migrating from an older version of Wear OS Compose or Horologist, updating an existing Wear Compose Material3 project, or adding features.
Unless otherwise indicated by the developer, use the latest stable version of Wear Compose Material3 from
{VERSION}(superseding any literal version strings in the migration guide).When migrating from Material 2.5 or Horologist, read the migration guide and use its official component mappings.
Before refactoring any component (for example,
Chip->Button), check the parameter names, slot types, and "Expressive" design tokens.Do not use the Horologist Composables, Compose Layout, or Compose Material libraries; replace Horologist components with Wear Compose M3 equivalents (
AppScaffold-> M3AppScaffold,ScreenScaffold-> M3ScreenScaffold,ScalingLazyColumn->TransformingLazyColumn,ResponsiveListHeader->ListHeader,PagerScreen->HorizontalPagerScaffold,Chip->Button,Confirmation->ConfirmationDialog).Always check against the component guidance in Capability 3.
Expect screenshot tests to fail when migrating or updating components: expected defaults for padding and positioning will have changed. Do not seek to artificially match the previous screenshot, but give preference to the Material3 defaults.
Capability 2: Component samples
Use this table of reference to find canonical samples for Wear Compose components. When working with a Wear Compose component, you must use the samples linked from the table to ensure you know how to correctly use it.
Important: Symbols marked with [alpha], [beta], or [rc] are only
available in that pre-release track and are not in stable {VERSION}. Do
not use them unless the project explicitly targets that pre-release version.
Material 3 components in androidx.wear.compose.material3.*
Foundation components in androidx.wear.compose.foundation.*
Navigation 3 components in androidx.wear.compose.navigation3.*
| Component / Symbol | Reference Samples |
|---|---|
rememberSwipeDismissableSceneStrategy | SwipeDismissableSceneStrategySample |
Capability 3: Component guidance
Mandatory: Use this capability as a checklist against any component use. It provides more holistic guidance on how to use each component in practice, beyond the component syntax.
AppScaffoldandScreenScaffold[ ] Use
AppScaffoldas the outer container, withScreenScaffoldchildren.[ ] Use only ONE
AppScaffoldand any number ofScreenScaffold.
ScalingLazyColumn- UseTransformingLazyColumninstead.TransformingLazyColumn- You will need the following imports:import androidx.wear.compose.foundation.lazy.TransformingLazyColumn import androidx.wear.compose.foundation.lazy.TransformingLazyColumnDefaults import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState // ... import androidx.wear.compose.material3.lazy.rememberTransformationSpec import androidx.wear.compose.material3.lazy.transformedHeight<br />
Canonical example:
val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding ) { item { ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) { Text(text = "Header") } } // ... other items item { Button( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding), transformation = SurfaceTransformation(transformationSpec), onClick = { /* ... */ }, icon = { Icon( imageVector = Icons.Default.Build, contentDescription = "build", ) }, ) { Text( text = "Build", maxLines = 1, overflow = TextOverflow.Ellipsis, ) } } } }<br />
[ ] Use
TransformingLazyColumninstead ofScalingLazyColumn.[ ] You must pass the
contentPaddingparameter fromScreenScaffoldto theTransformingLazyColumn.[ ] Use the
minimumVerticalContentPaddingmodifier to achieve required padding top and bottom.This expects a value from defaults, such as
ButtonDefaults,CardDefaults,ListHeaderDefaults.Note: This is a scoped modifier available within
TransformingLazyColumnItemScope.
[ ] Ensure items morph and scale (apply to components within
TransformingLazyColumn, not the list itself):[ ] Use
Modifier.transformedHeight(this, transformationSpec).[ ] Use
transformation = SurfaceTransformation(transformationSpec).
[ ] If configuring a list for snapping, use
flingBehaviorandrotaryScrollableBehaviortogether:
val columnState = rememberTransformingLazyColumnState() ScreenScaffold(scrollState = columnState) { contentPadding -> TransformingLazyColumn( state = columnState, flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState), rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState) ) { // ... // ... } }<br />
ScreenScaffold[ ] Guard the
scrollIndicatorwith!LocalScrollCaptureInProgress.current(androidx.compose.ui.platform).
EdgeButton[ ] Do NOT use as the final item within a
TransformingLazyColumn. Instead, use the slot inScreenScaffold.[ ] When used in a
TransformingLazyColumn, add the required overscroll behavior:
val columnState = rememberTransformingLazyColumnState() ScreenScaffold( scrollState = columnState, edgeButton = { EdgeButton( onClick = { /* TODO */ }, modifier = Modifier.scrollable( columnState, orientation = Orientation.Vertical, reverseDirection = true, // Apply overscroll to the EdgeButton for proper scrolling behavior. overscrollEffect = rememberOverscrollEffect(), ) ) { Text("More") } } ) { contentPadding -> TransformingLazyColumn( contentPadding = contentPadding, state = columnState, ) { // ... // ... } }<br />
Column[ ] USE as a direct child of
ScreenScaffoldif the screen will never scroll, even with the largest system font.[ ] Use
TransformingLazyColumninstead for all other cases.
Styles
[ ] Do NOT hard-code text sizes, use
typographyfromMaterialTheme.[ ] Do NOT hard-code colors, use
colorSchemefromMaterialTheme.
Use component defaults:
[ ] Components such as
Buttonhave a correspondingButtonDefaultsobject.[ ] Check for and use the
*Defaultsobject for any component when working with padding and styling values, in preference to hard-coded values.
Use Wear-specific preview annotations (
androidx.wear.compose.ui.tooling.preview):[ ]
@WearPreviewDevices[ ]
@WearPreviewFontScales[ ] Ensure the
androidx.wear.compose:compose-ui-toolingdependency is included.
Ambient mode
[ ] Use
LocalAmbientModeManager(provided byCompositionLocalProviderandrememberAmbientModeManager()) instead ofAmbientLifecycleObserver.
Navigation
[ ] When adding navigation fresh, use Navigation3 (
androidx.wear.compose:compose-navigation3).[ ] Use
rememberSwipeDismissableSceneStrategy()/SwipeDismissableSceneStrategy(androidx.wear.compose.navigation3).
Comments
[ ] Where any Kotlin file has been modified, ensure that the existing comments are up to date and accurately reflect any changes to the implementation.
HorizontalPagerorVerticalPager[ ] Use the Composable hierarchy in this order:
AppScaffold,HorizontalPagerScaffold,HorizontalPager,AnimatedPage,ScreenScaffold. Or similarly forVerticalPager.
Files
- ATTRIBUTION.mdAdded by AutoGineer952 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md38.2 KiB
- references/android/training/wearables/compose/migrate-to-material3.md89.1 KiB
- references/foundation/AmbientModeSample.kt.md5.0 KiB
- references/foundation/CurvedWorldSample.kt.md14.3 KiB
- references/foundation/ExpandableSample.kt.md3.6 KiB
- references/foundation/HierarchicalFocusSample.kt.md5.4 KiB
- references/foundation/PagerSamples.kt.md2.0 KiB
- references/foundation/RotarySamples.kt.md6.0 KiB
- references/foundation/SwipeToDismissBoxSample.kt.md7.3 KiB
- references/foundation/TransformingLazyColumnSample.kt.md12.9 KiB
- references/material3/AlertDialogSample.kt.md15.1 KiB
- references/material3/AnimatedTextSample.kt.md6.2 KiB
- references/material3/ButtonGroupSample.kt.md3.3 KiB
- references/material3/ButtonSample.kt.md17.0 KiB
- references/material3/CardSample.kt.md15.2 KiB
- references/material3/CheckboxButtonSample.kt.md2.3 KiB
- references/material3/ConfirmationDialogSample.kt.md5.4 KiB
- references/material3/CurvedTextSamples.kt.md2.9 KiB
- references/material3/DatePickerSample.kt.md4.7 KiB
- references/material3/DynamicColorSchemeSample.kt.md3.0 KiB
- references/material3/EdgeButtonSample.kt.md2.3 KiB
- references/material3/FadingExpandingLabelSample.kt.md2.1 KiB
- references/material3/IconButtonSample.kt.md3.9 KiB
- references/material3/IconToggleButtonSample.kt.md3.6 KiB
- references/material3/LevelIndicatorSample.kt.md2.5 KiB
- references/material3/LinearProgressIndicatorSample.kt.md1.8 KiB
- references/material3/ListHeaderSample.kt.md7.6 KiB
- references/material3/OneHandedGestureSamples.kt.md31.5 KiB
- references/material3/OpenOnPhoneDialogSample.kt.md2.0 KiB
- references/material3/PageIndicatorSample.kt.md4.1 KiB
- references/material3/PagerScaffoldSample.kt.md8.5 KiB
- references/material3/PickerGroupSample.kt.md5.8 KiB
- references/material3/PickerSample.kt.md3.6 KiB
- references/material3/PlaceholderSample.kt.md6.5 KiB
- references/material3/ProgressIndicatorSample.kt.md8.8 KiB
- references/material3/RadioButtonSample.kt.md4.2 KiB
- references/material3/ScaffoldSample.kt.md6.2 KiB
- references/material3/ScrollAwaySample.kt.md3.7 KiB
- references/material3/ScrollIndicatorSample.kt.md2.4 KiB
- references/material3/SliderSample.kt.md2.4 KiB
- references/material3/StepperSample.kt.md5.2 KiB
- references/material3/SurfaceTransformationSample.kt.md6.0 KiB
- references/material3/SwipeToDismissBoxSample.kt.md7.3 KiB
- references/material3/SwipeToRevealSample.kt.md13.7 KiB
- references/material3/SwitchButtonSample.kt.md2.3 KiB
- references/material3/TextButtonSample.kt.md3.0 KiB
- references/material3/TextToggleButtonSample.kt.md2.3 KiB
- references/material3/TimePickerSample.kt.md5.5 KiB
- references/material3/TimeTextSample.kt.md2.5 KiB
- references/material3/TransformationSpecSample.kt.md9.9 KiB
- references/material3/TransformingLazyColumnNotificationsSample.kt.md3.7 KiB
- references/material3/TransformingLazyColumnSample.kt.md13.0 KiB
- references/navigation3/SwipeDismissableSceneStrategySample.kt.md8.3 KiB
references/android/training/wearables/compose/migrate-to-material3.md
Material 3 Expressive is the next evolution of Material Design. It includes updated theming, components, and personalization features like dynamic color.
This guide focuses on migrating from the Wear Compose Material 2.5 (androidx.wear.compose) Jetpack library to the Wear Compose Material 3 (androidx.wear.compose.material3) Jetpack library for apps.
[!NOTE] Note: This guide uses abbreviation "M3" to refer to the interchangeable terms of "Material 3 Expressive" and the equivalent Jetpack library for Compose on Wear OS (androidx.wear.compose.material3). The abbreviation "M2.5" is used to refer to the interchangeable terms of "Material 2.5" and the equivalent Jetpack library for Compose on Wear OS (androidx.wear.compose.material).
Approaches
For migrating your app code from M2.5 to M3, follow the same approach described in the Compose Material migration phone guidance, in particular:
You shouldn't use both M2.5 and M3 in a single app long-term.
You should no longer use the Horologist Composables, Compose Layout, or Compose Material libraries. Instead, use the components in M3.
Adopt a phased approach.
Dependencies
M3 has a separate package and version to M2.5:
M2.5
implementation("androidx.wear.compose:compose-material:1.4.0")M3
implementation("androidx.wear.compose:compose-material3:1.8.0-alpha02")See the latest M3 versions on the Wear Compose releases page.
Wear Compose Foundation library version 1.8.0-alpha02 introduced
some new components that are designed to work with Material 3 components.
Similarly, SwipeDismissableNavHost from Wear Compose Navigation library has an
updated animation when running on Wear OS 6 (API level 36) or higher. When
updating to Wear Compose Material 3 version, we suggest to also update the Wear
Compose Foundation and Navigation libraries:
implementation("androidx.wear.compose:compose-foundation:1.8.0-alpha02")
implementation("androidx.wear.compose:compose-navigation:1.8.0-alpha02")Theme
In both M2.5 and M3, the theme composable is named MaterialTheme, but the
import packages and parameters differ. In M3, the Colors parameter has been
renamed to ColorScheme and MotionScheme has been introduced for implementing
transitions.
M2.5
import androidx.wear.compose.material.MaterialTheme
MaterialTheme(
colors = AppColors,
typography = AppTypography,
shapes = AppShapes,
content = content
)M3
import androidx.wear.compose.material3.MaterialTheme
// ...
MaterialTheme(
colorScheme = ColorScheme(),
typography = Typography(),
shapes = Shapes(),
motionScheme = MotionScheme.standard(),
content = { /*content here*/ }
)<br />
Color
The color system in M3 is significantly different from M2.5. The number of color
parameters has increased, they have different names, and they map differently to
M3 components. In Compose, this applies to the M2.5 Colors class, the M3
ColorScheme class, and related functions:
M2.5
import androidx.wear.compose.material.Colors
val appColorScheme: Colors = Colors(
// M2.5 Color parameters
)M3
import androidx.wear.compose.material3.ColorScheme
// ...
val appColorScheme: ColorScheme = ColorScheme(
// M3 ColorScheme parameters
)<br />
The following table describes the key differences between M2.5 and M3:
| M2.5 | M3 |
|---|---|
Colors | Has been renamed to ColorScheme |
| 13 colors | 29 colors |
| N/A | New dynamic color theming |
| N/A | New tertiary colors for more expression |
Dynamic color theming
A new feature in M3 is dynamic color theming. If users change the watch face colors, the colors in the UI change to match.
Use the dynamicColorScheme function to implement dynamic color scheme
and provide a defaultColorScheme as a fallback in case dynamic color scheme is
not available.
@Composable
fun myApp() {
val dynamicColorScheme = dynamicColorScheme(LocalContext.current)
MaterialTheme(colorScheme = dynamicColorScheme ?: myBrandColors) {}
}
internal val myBrandColors: ColorScheme = ColorScheme( /* Specify colors here */)<br />
Typography
The typography system in M3 is different from M2.5 and it includes the following features:
Nine new text styles
Flex fonts, which allow for customization of the type scales for different weights, widths, and roundness
AnimatedText, which uses flex fonts
M2.5
import androidx.wear.compose.material.Typography
val Typography = Typography(
// M2.5 TextStyle parameters
)M3
import androidx.wear.compose.material3.Typography
val Typography = Typography(
// M3 TextStyle parameters
)<br />
Flex fonts
Flex Fonts allow designers to specify the type width and weight for specific sizes.
Text styles
The following TextStyles are available in M3. These are employed by default by various M3 components.
| Typography | TextStyle |
|---|---|
| Display | displayLarge, displayMedium, displaySmall |
| Title | titleLarge, titleMedium, titleSmall |
| Label | labelLarge, labelMedium, labelSmall |
| Body | bodyLarge, bodyMedium, bodySmall, bodyExtraSmall |
| Numeral | numeralExtraLarge, numeralLarge, numeralMedium, numeralSmall, numeralExtraSmall |
| Arc | arcLarge, arcMedium, arcSmall |
Shape
The shape system in M3 is different from M2.5. The number of shape parameters has increased, they're named differently, and they map differently to M3 components. The following shape sizes are available:
Extra-small
Small
Medium
Large
Extra-large
In Compose, this applies to the M2.5 Shapes class and the M3
Shapes class:
M2.5
import androidx.wear.compose.material.Shapes
val Shapes = Shapes(
// M2.5 Shapes parameters
)M3
import androidx.wear.compose.material3.Shapes
val Shapes = Shapes(
// M3 Shapes parameters
)<br />
[!NOTE] Note: For shapes, we generally recommend using the default Material 3 Wear shapes which are optimized for round devices.
Use the Shapes parameter mapping from Migrate from Material 2 to Material 3 in Compose as a starting point.
Shape morphing
M3 introduces Shape Morphing: shapes now morph in response to interactions.
Shape Morphing behavior is available as a variation on a number of round buttons, see the following list of buttons that support Shape Morphing:
| Buttons | Shape morphing function |
|---|---|
IconButton | IconButtonDefaults.animatedShapes animates the icon button on press |
IconToggleButton | IconToggleButtonDefaults.animatedShapes animates the icon toggle button on press and IconToggleButtonDefaults.variantAnimatedShapes animates the icon toggle button on press and check/uncheck |
TextButton | TextButtonDefaults.animatedShapes animates the text button on press |
TextToggleButton | TextToggleButtonDefaults.animatedShapes animates the text toggle on press and TextToggleButtonDefaults.variantAnimatedShapes animates the text toggle on press and check/uncheck |
Components and Layout
Most components and layouts from M2.5 are available in M3. However, some M3 components and layouts didn't exist in M2.5. Furthermore, some M3 components have more variations than their equivalents in M2.5.
While some components require special considerations, the following function mappings are recommended as a starting point:
Here is a list of common Material 3 components and their Material 2.5 equivalents:
And finally a list of some relevant components from Wear Compose Foundation library:
| Wear Compose Foundation 1.8.0-alpha02 | |
|---|---|
| androidx.wear.compose.foundation.hierarchicalFocusGroup | Used to annotate composables in an application, to keep track of the active part of the composition and coordinate focus. |
| androidx.wear.compose.foundation.pager.HorizontalPager | A horizontally scrolling pager, built on the Compose Foundation components with Wear-specific enhancements to improve performance and adherence to Wear OS guidelines. |
| androidx.wear.compose.foundation.pager.VerticalPager | A vertically scrolling pager, built on the Compose Foundation components with Wear-specific enhancements to improve performance and adherence to Wear OS guidelines. |
| androidx.wear.compose.foundation.lazy.TransformingLazyColumn | Can be used instead of ScalingLazyColumn to add scroll transform effects to each item. |
Buttons
Buttons in M3 are different from M2.5. The M2.5 Chip has been replaced by
Button. Button implementation provides default values for Text
maxLines and textAlign. Those default values can be overridden in the Text
element.
M2.5
import androidx.wear.compose.material.Chip
//M2.5 Buttons
Chip(...)
CompactChip(...)
Button(...)M3
//M3 Buttons
Button(onClick = { }){}
CompactButton(onClick = { }){}
IconButton(onClick = { }){}
TextButton(onClick = { }){}<br />
M3 also includes new button variations. Check them out on the Compose Material 3 API reference overview.
M3 introduces a new button: EdgeButton. EdgeButton is available in 4
different sizes: extra small, small, medium, and large. EdgeButton
implementation provide a default value for maxLines depending on the size
which can be customized.
If you are using TransformingLazyColumn or ScalingLazyColumn, pass the
EdgeButton into the ScreenScaffold so that it morphs, changing its shape
with scrolling, instead of adding an EdgeButton as the final list item. See
the following code to check how to use EdgeButton with ScreenScaffold and
TransformingLazyColumn.
val state = rememberTransformingLazyColumnState()
ScreenScaffold(
scrollState = state,
edgeButton = {
EdgeButton(
onClick = { },
modifier = Modifier.scrollable(
state,
orientation = Orientation.Vertical,
reverseDirection = true,
// Apply overscroll to the EdgeButton for proper scrolling behavior.
overscrollEffect = rememberOverscrollEffect(),
),
) {
Text(stringResource(R.string.show))
}
},
) { contentPadding ->
TransformingLazyColumn(state = state, contentPadding = contentPadding) {
// additional code here
// ...
}
}<br />
Scaffold
Scaffold in M3 is different from M2.5. In M3, AppScaffold and the new
ScreenScaffold composable have replaced Scaffold. AppScaffold and
ScreenScaffold lay out the structure of a screen and coordinate transitions of
the ScrollIndicator and TimeText components.
AppScaffold allows static screen elements such as TimeText to remain visible
during in-app transitions such as swipe-to-dismiss. It provides a slot for the
main application content, which will usually be supplied by a navigation
component such as SwipeDismissableNavHost
You declare one AppScaffold for Activity and use a ScreenScaffold for each
Screen.
AppScaffold adds a default TimeTextcomponent to the screens. You can
override it if you want to customize it by using the timeText parameter.
M2.5
import androidx.wear.compose.material.Scaffold
Scaffold {...}M3
AppScaffold {
val navController = rememberSwipeDismissableNavController()
SwipeDismissableNavHost(
navController = navController,
startDestination = "message_list"
) {
composable("message_list") {
MessageList(onMessageClick = { id ->
navController.navigate("message_detail/$id")
})
}
composable("message_detail/{id}") {
MessageDetail(id = it.arguments?.getString("id")!!)
}
}
}
}
// Implementation of one of the screens in the navigation
@Composable
fun MessageDetail(id: String) {
// .. Screen level content goes here
val scrollState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
scrollState = scrollState,
) { contentPadding ->
// Screen content goes here
// ...<br />
[!NOTE] Note:
AppScaffoldandScreenScaffoldfrom Horologist haven't been migrated to M3. To maintain correct scrolling behavior andTimeTextelements, migrate to theAppScaffoldandScreenScaffoldfrom M3.
If you are using a HorizontalPager with HorizontalPageIndicator, you
can migrate to HorizontalPagerScaffold. HorizontalPagerScaffold is
placed within an AppScaffold. AppScaffold and HorizontalPagerScaffold lay
out the structure of a Pager and coordinate transitions of the
HorizontalPageIndicator and TimeText components.
HorizontalPagerScaffold displays the HorizontalPageIndicator at the
center-end of the screen by default and coordinates showing and hiding
TimeText and HorizontalPageIndicator according to whether the Pager is
being paged, this is determined by the PagerState.
There's also a new AnimatedPage component, which animates a page within a
Pager with a scaling and scrim effect based on its position.
AppScaffold {
val pagerState = rememberPagerState(pageCount = { 10 })
HorizontalPagerScaffold(pagerState = pagerState) {
HorizontalPager(
state = pagerState,
flingBehavior =
PagerScaffoldDefaults.snapWithSpringFlingBehavior(
state = pagerState
),
) { page ->
AnimatedPage(pageIndex = page, pagerState = pagerState) {
val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
scrollState = columnState,
) { contentPadding ->
TransformingLazyColumn(
state = columnState,
contentPadding = contentPadding,
) {
item {
ListHeader(
modifier = Modifier
.fillMaxWidth()
.transformedHeight(this, transformationSpec)
.minimumVerticalContentPadding(
ListHeaderDefaults.minimumTopListContentPadding
),
transformation = SurfaceTransformation(transformationSpec),
) {
Text(text = "Pager sample")
}
}
item {
Card(
modifier = Modifier
.fillMaxWidth()
.transformedHeight(this, transformationSpec)
.minimumVerticalContentPadding(
CardDefaults.minimumVerticalListContentPadding
),
transformation = SurfaceTransformation(transformationSpec),
) {
if (page == 0) {
Text(text = "Page #$page. Swipe right")
} else {
Text(text = "Page #$page. Swipe left and right")
}
}
}
}
}
}
}
}
}<br />
Finally, M3 introduces a VerticalPagerScaffold which follows the same
pattern as the HorizontalPagerScaffold:
@Composable
fun VerticalPagerScaffoldSample() {
AppScaffold {
val pagerState = rememberPagerState(pageCount = { 10 })
VerticalPagerScaffold(pagerState = pagerState) {
VerticalPager(
state = pagerState,
flingBehavior =
PagerScaffoldDefaults.snapWithSpringFlingBehavior(
state = pagerState
),
) { page ->
AnimatedPage(pageIndex = page, pagerState = pagerState) {
ScreenScaffold {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Text(text = "Page #$page")
Spacer(modifier = Modifier.height(8.dp))
Text(text = "Swipe up and down")
}
}
}
}
}
}
}<br />
Placeholder
There are some API changes between M2.5 and M3. M3 provides two placeholder modifiers:
Modifier.placeholder, which is drawn instead of content that is not yet loadedA placeholder shimmer effect
Modifier.placeholderShimmerwhich provides a placeholder shimmer effect which runs in an animation loop while waiting for the data to load.
See the following table for additional changes to the Placeholder component.
| M2.5 | M3 |
|---|---|
PlaceholderState.startPlaceholderAnimation | Has been removed |
PlaceholderState.placeholderProgression | Has been removed |
PlaceholderState.isShowContent | Replaced by PlaceholderState.isVisible (inverted boolean) |
PlaceholderState.isWipeOff | Has been removed |
PlaceholderDefaults.painterWithPlaceholderOverlayBackgroundBrush | Has been removed |
PlaceholderDefaults.placeholderBackgroundBrush | Has been removed |
PlaceholderDefaults.placeholderChipColors | Has been removed |
SwipeDismissableNavHost
SwipeDismissableNavHost is part of wear.compose.navigation. When this
component is used with M3, the M3 MaterialTheme updates the
LocalSwipeToDismissBackgroundScrimColor and
LocalSwipeToDismissContentScrimColor.
TransformingLazyColumn
TransformingLazyColumn is part of androidx.wear.compose.foundation.lazy and
adds support for scaling and morphing animations on list items during scrolling,
enhancing the user experience. It is strongly recommended that apps migrate from
ScalingLazyColumn to TransformingLazyColumn.
Similarly to ScalingLazyColumn, it provides
rememberTransformingLazyColumnState() to create a
TransformingLazyColumnState that is remembered across compositions.
For adding scaling and morphing animations, add the following to each list item:
Modifier.transformedHeight, which lets you calculate transformed height of the items using aTransformationSpec, you can userememberTransformationSpec()unless you need further customization.A
SurfaceTransformation
To verify that the padding is correct at the top and bottom of the list, use the
minimumVerticalContentPadding modifier.
val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
scrollState = columnState
) { contentPadding ->
TransformingLazyColumn(
state = columnState,
contentPadding = contentPadding
) {
item {
ListHeader(
modifier = Modifier
.fillMaxWidth()
.transformedHeight(this, transformationSpec)
.minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
transformation = SurfaceTransformation(transformationSpec)
) {
Text(text = "Header")
}
}
// ... other items
item {
Button(
modifier = Modifier
.fillMaxWidth()
.transformedHeight(this, transformationSpec)
.minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
transformation = SurfaceTransformation(transformationSpec),
onClick = { /* ... */ },
icon = {
Icon(
imageVector = Icons.Default.Build,
contentDescription = "build",
)
},
) {
Text(
text = "Build",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
}<br />
Useful links
To learn more about migrating from M2.5 to M3 in Compose, consult the following additional resources.
Samples
API reference and source code
Design
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs network access
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Google LLC
- Publisher
- Android (Google) (Official)
- Distributed by
- Android (Google)
- Source
- android/skills · wear/wear-compose-m3 · commit bf68e2d
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.txt)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Google LLC or Android (Google).
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download wear-compose-m3.zip