Material 3 Expressive ist die nächste Entwicklungsstufe von Material Design. Es enthält aktualisierte Designs, Komponenten und Personalisierungsfunktionen wie dynamische Farben.
In diesem Leitfaden wird die Migration von der Jetpack-Bibliothek Wear Compose Material 2.5 (androidx.wear.compose) zur Jetpack-Bibliothek Wear Compose Material 3 (androidx.wear.compose.material3) für Apps beschrieben.
Ansätze
Wenn Sie Ihren App-Code von M2.5 zu M3 migrieren möchten, gehen Sie wie in der Anleitung zur Migration von Compose Material für Smartphones beschrieben vor. Beachten Sie insbesondere Folgendes:
- Sie sollten M2.5 und M3 nicht langfristig in einer einzigen App verwenden.
- Du solltest die Bibliotheken „Horologist Composables“, „Compose Layout“ oder „Compose Material“ nicht mehr verwenden. Verwenden Sie stattdessen die Komponenten in M3.
- Schrittweise vorgehen
Abhängigkeiten
M3 hat ein separates Paket und eine separate Version zu M2.5:
M2.5
implementation("androidx.wear.compose:compose-material:1.4.0")
M3
implementation("androidx.wear.compose:compose-material3:1.8.0-alpha02")
Die neuesten M3-Versionen finden Sie auf der Seite mit den Wear Compose-Releases.
In Version 1.8.0-alpha02 der Wear Compose Foundation-Bibliothek wurden einige neue Komponenten eingeführt, die für die Verwendung mit Material 3-Komponenten entwickelt wurden.
Auch SwipeDismissableNavHost aus der Wear Compose Navigation-Bibliothek hat eine aktualisierte Animation, wenn es unter Wear OS 6 (API-Level 36) oder höher ausgeführt wird. Wenn ihr auf die Wear Compose Material 3-Version aktualisiert, empfehlen wir, auch die Wear Compose Foundation- und Navigation-Bibliotheken zu aktualisieren:
implementation("androidx.wear.compose:compose-foundation:1.8.0-alpha02")
implementation("androidx.wear.compose:compose-navigation:1.8.0-alpha02")
Design
Sowohl in M2.5 als auch in M3 heißt die komponierbare Funktion für das Design MaterialTheme, aber die Importpakete und Parameter unterscheiden sich. In M3 wurde der Parameter Colors in ColorScheme umbenannt und MotionScheme wurde für die Implementierung von Übergängen eingeführt.
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*/ } )
Farbe
Das Farbsystem in M3 unterscheidet sich erheblich von dem in M2.5. Die Anzahl der Farbparameter hat sich erhöht, sie haben andere Namen und werden anders den M3-Komponenten zugeordnet. In Compose gilt dies für die M2.5-Klasse Colors, die M3-Klasse ColorScheme und zugehörige Funktionen:
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 )
In der folgenden Tabelle werden die wichtigsten Unterschiede zwischen M2.5 und M3 beschrieben:
| M2.5 | M3 |
|---|---|
Colors |
Wurde in „ColorScheme“ umbenannt |
| 13 Farben | 29 Farben |
| – | Neues dynamisches Farbschema |
| – | Neue Tertiärfarben für mehr Ausdruck |
Dynamische Farbthemen
Eine neue Funktion in M3 ist das dynamische Farbschema. Wenn Nutzer die Farben des Zifferblatts ändern, werden die Farben in der Benutzeroberfläche entsprechend angepasst.
Verwenden Sie die Funktion dynamicColorScheme, um ein dynamisches Farbschema zu implementieren, und geben Sie ein defaultColorScheme als Fallback an, falls das dynamische Farbschema nicht verfügbar ist.
@Composable fun myApp() { val dynamicColorScheme = dynamicColorScheme(LocalContext.current) MaterialTheme(colorScheme = dynamicColorScheme ?: myBrandColors) {} } internal val myBrandColors: ColorScheme = ColorScheme( /* Specify colors here */)
Typografie
Das Typografiesystem in M3 unterscheidet sich von M2.5 und umfasst die folgenden Funktionen:
- Neun neue Textstile
- Flex-Schriftarten, mit denen die Schriftgrößen für verschiedene Stärken, Breiten und Rundungen angepasst werden können
AnimatedText, die flexible Schriftarten verwendet
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 )
Flexible Schriftarten
Mit Flex Fonts können Designer die Schriftbreite und -stärke für bestimmte Größen festlegen.
Textstile
Die folgenden TextStyles sind in M3 verfügbar. Diese werden standardmäßig von verschiedenen M3-Komponenten verwendet.
| Typografie | TextStyle |
|---|---|
| Display | displayLarge, displayMedium, displaySmall |
| Titel | titleLarge, titleMedium, titleSmall |
| Label | labelLarge, labelMedium, labelSmall |
| Body | bodyLarge, bodyMedium, bodySmall, bodyExtraSmall |
| Zahlwort | numeralExtraLarge, numeralLarge, numeralMedium, numeralSmall, numeralExtraSmall |
| Bogen | arcLarge, arcMedium, arcSmall |
Form
Das Formensystem in M3 unterscheidet sich von dem in M2.5. Die Anzahl der Formparameter hat sich erhöht, sie haben andere Namen und werden anders auf M3-Komponenten abgebildet. Folgende Formgrößen sind verfügbar:
- Sehr klein
- Klein
- Mittel
- Groß
- Sehr groß
In Compose gilt dies für die M2.5-Klasse Shapes und die M3-Klasse Shapes:
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 )
Verwenden Sie die Parameterzuordnung für Formen aus Von Material 2 zu Material 3 in Compose migrieren als Ausgangspunkt.
Form-Morphing
M3 führt Shape Morphing ein: Formen verändern sich jetzt als Reaktion auf Interaktionen.
Das Verhalten „Form-Morphing“ ist als Variante für eine Reihe von runden Schaltflächen verfügbar. Hier finden Sie eine Liste der Schaltflächen, die Form-Morphing unterstützen:
| Tasten | Funktion zum Morphen von Formen |
|---|---|
IconButton |
IconButtonDefaults.animatedShapes animiert die Symbolschaltfläche beim Drücken. |
IconToggleButton |
IconToggleButtonDefaults.animatedShapes animiert den Ein/Aus-Button mit Symbol beim Drücken und IconToggleButtonDefaults.variantAnimatedShapes animiert den Ein/Aus-Button mit Symbol beim Drücken und Aktivieren/Deaktivieren. |
TextButton |
TextButtonDefaults.animatedShapes animiert die Textschaltfläche beim Drücken. |
TextToggleButton |
TextToggleButtonDefaults.animatedShapes animiert die Text-Umschalttaste beim Drücken und TextToggleButtonDefaults.variantAnimatedShapes animiert die Text-Umschalttaste beim Drücken und Aktivieren/Deaktivieren. |
Komponenten und Layout
Die meisten Komponenten und Layouts aus M2.5 sind in M3 verfügbar. Einige M3-Komponenten und -Layouts gab es in M2.5 jedoch nicht. Außerdem gibt es für einige M3-Komponenten mehr Varianten als für die entsprechenden M2.5-Komponenten.
Für einige Komponenten sind besondere Überlegungen erforderlich. Die folgenden Funktionszuordnungen werden jedoch als Ausgangspunkt empfohlen:
Hier finden Sie eine Liste gängiger Material 3-Komponenten und ihrer Material 2.5-Entsprechungen:
Und schließlich eine Liste mit einigen relevanten Komponenten aus der Wear Compose Foundation-Bibliothek:
| Wear Compose Foundation 1.8.0-alpha02 | |
|---|---|
| androidx.wear.compose.foundation.hierarchicalFocusGroup | Wird verwendet, um Composables in einer Anwendung zu annotieren, den aktiven Teil der Komposition im Blick zu behalten und den Fokus zu koordinieren. |
| androidx.wear.compose.foundation.pager.HorizontalPager | Ein horizontal scrollender Pager, der auf den Compose Foundation-Komponenten basiert und Wear-spezifische Verbesserungen enthält, um die Leistung und die Einhaltung der Wear OS-Richtlinien zu verbessern. |
| androidx.wear.compose.foundation.pager.VerticalPager | Ein vertikal scrollender Pager, der auf den Compose Foundation-Komponenten basiert und Wear-spezifische Verbesserungen enthält, um die Leistung zu steigern und die Einhaltung der Wear OS-Richtlinien zu verbessern. |
| androidx.wear.compose.foundation.lazy.TransformingLazyColumn | Kann anstelle von ScalingLazyColumn verwendet werden, um jedem Element Scroll-Transformations-Effekte hinzuzufügen. |
Tasten
Die Schaltflächen in M3 unterscheiden sich von denen in M2.5. Der M2.5-Chip wurde durch eine Taste ersetzt. Die Button-Implementierung stellt Standardwerte für Text, maxLines und textAlign bereit. Diese Standardwerte können im Element Text überschrieben werden.
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 = { }){}
M3 enthält auch neue Schaltflächenvarianten. Eine Übersicht finden Sie in der Compose Material 3 API-Referenz.
In M3 wird ein neuer Button eingeführt: EdgeButton. Die EdgeButton sind in vier verschiedenen Größen erhältlich: sehr klein, klein, mittelgroß und groß. Die EdgeButton-Implementierung bietet je nach Größe einen Standardwert für maxLines, der angepasst werden kann.
Wenn Sie TransformingLazyColumn oder ScalingLazyColumn verwenden, übergeben Sie die EdgeButton an die ScreenScaffold, damit sie sich beim Scrollen verändert, anstatt eine EdgeButton als letztes Listenelement hinzuzufügen. Im folgenden Code sehen Sie, wie Sie EdgeButton mit ScreenScaffold und TransformingLazyColumn verwenden.
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 // ... } }
Scaffold
Scaffold in M3 unterscheidet sich von M2.5. In M3 wurden Scaffold durch AppScaffold und das neue ScreenScaffold-Composable ersetzt. AppScaffold und ScreenScaffold legen die Struktur eines Bildschirms fest und koordinieren die Übergänge der Komponenten ScrollIndicator und TimeText.
Mit AppScaffold können statische Bildschirmelemente wie TimeText bei In-App-Übergängen wie dem Schließen durch Wischen sichtbar bleiben. Es bietet einen Slot für den Hauptinhalt der Anwendung, der normalerweise von einer Navigationskomponente wie SwipeDismissableNavHost bereitgestellt wird.
Sie deklarieren eine AppScaffold für die Aktivität und verwenden für jeden Bildschirm eine ScreenScaffold.
AppScaffold fügt den Bildschirmen eine Standardkomponente TimeText hinzu. Sie können ihn mit dem Parameter timeText überschreiben, wenn Sie ihn anpassen möchten.
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 // ...
Wenn Sie einen HorizontalPager mit HorizontalPageIndicator verwenden, können Sie zu HorizontalPagerScaffold migrieren. HorizontalPagerScaffold wird in einem AppScaffold platziert. AppScaffold und HorizontalPagerScaffold legen die Struktur eines Pagers fest und koordinieren die Übergänge der Komponenten HorizontalPageIndicator und TimeText.
HorizontalPagerScaffold zeigt standardmäßig HorizontalPageIndicator in der Mitte des Bildschirms an und koordiniert das Ein- und Ausblenden von TimeText und HorizontalPageIndicator, je nachdem, ob Pager seitenweise angezeigt wird. Dies wird durch PagerState bestimmt.
Außerdem gibt es eine neue AnimatedPage-Komponente, die eine Seite innerhalb eines Pagers mit einem Skalierungs- und Scrim-Effekt basierend auf ihrer Position animiert.
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") } } } } } } } } }
Schließlich wird in M3 ein VerticalPagerScaffold eingeführt, der dem gleichen Muster wie der HorizontalPagerScaffold folgt:
@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") } } } } } } }
Platzhalter
Es gibt einige API-Änderungen zwischen M2.5 und M3. M3 bietet zwei Platzhaltermodifikatoren:
Modifier.placeholder, das anstelle von noch nicht geladenen Inhalten gezeichnet wird- Ein Platzhalter-Schimmereffekt
Modifier.placeholderShimmer, der in einer Animationsschleife ausgeführt wird, während auf das Laden der Daten gewartet wird.
In der folgenden Tabelle finden Sie weitere Änderungen an der Komponente Placeholder.
| M2.5 | M3 |
|---|---|
PlaceholderState.startPlaceholderAnimation |
Wurde entfernt |
PlaceholderState.placeholderProgression |
Wurde entfernt |
PlaceholderState.isShowContent |
Ersetzt durch PlaceholderState.isVisible (invertierter boolescher Wert) |
PlaceholderState.isWipeOff |
Wurde entfernt |
PlaceholderDefaults.painterWithPlaceholderOverlayBackgroundBrush |
Wurde entfernt |
PlaceholderDefaults.placeholderBackgroundBrush |
Wurde entfernt |
PlaceholderDefaults.placeholderChipColors |
Wurde entfernt |
SwipeDismissableNavHost
SwipeDismissableNavHost ist Teil von wear.compose.navigation. Wenn diese Komponente mit M3 verwendet wird, aktualisiert das M3-MaterialTheme die LocalSwipeToDismissBackgroundScrimColor und die LocalSwipeToDismissContentScrimColor.
TransformingLazyColumn
TransformingLazyColumn ist Teil von androidx.wear.compose.foundation.lazy und bietet Unterstützung für Skalierungs- und Morphing-Animationen für Listenelemente beim Scrollen, was die Nutzerfreundlichkeit verbessert. Es wird dringend empfohlen, Apps von ScalingLazyColumn zu TransformingLazyColumn zu migrieren.
Ähnlich wie ScalingLazyColumn bietet es rememberTransformingLazyColumnState(), um einen TransformingLazyColumnState zu erstellen, der über Kompositionen hinweg gespeichert wird.
Wenn Sie Skalierungs- und Morphing-Animationen hinzufügen möchten, fügen Sie jedem Listenelement Folgendes hinzu:
Modifier.transformedHeight, mit dem Sie die transformierte Höhe der Elemente mithilfe einesTransformationSpecberechnen können, können SierememberTransformationSpec()verwenden, sofern Sie keine weiteren Anpassungen benötigen.- Ein
SurfaceTransformation
Mit dem Modifikator minimumVerticalContentPadding kannst du prüfen, ob das Padding oben und unten in der Liste korrekt ist.
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, ) } } } }
Nützliche Links
Weitere Informationen zur Migration von M2.5 zu M3 in Compose finden Sie in den folgenden zusätzlichen Ressourcen.