Mit Listen können Nutzer auf Wear OS-Geräten ein Element aus einer Reihe von Optionen auswählen.
Viele Wear OS-Geräte haben runde Displays, wodurch es schwieriger ist, Listenelemente zu sehen, die sich oben und unten auf dem Display befinden. Aus diesem Grund,
Compose für Wear OS enthält eine Version der Klasse LazyColumn namens
TransformingLazyColumn, die Skalierungs- und Morphing-Animationen unterstützt.
Wenn Elemente an die Ränder verschoben werden, werden sie kleiner und blenden aus.
So wenden Sie die empfohlenen Skalierungs- und Scrolling-Effekte an:
- Verwenden Sie
Modifier.transformedHeight, damit Compose die Höhenänderung berechnen kann, wenn das Element durch den Bildschirm scrollt. - Verwenden Sie
transformation = SurfaceTransformation(transformationSpec), um die visuellen Effekte anzuwenden, einschließlich der Verkleinerung des Inhalts des Elements. - Verwenden Sie eine benutzerdefinierte
TransformationSpecfür Komponenten, dietransformationnicht als Parameter verwenden, z. B.Text.
Die folgende Animation zeigt, wie ein Listenelement skaliert und seine Form ändert, wenn es sich dem oberen und unteren Rand des Displays nähert:
Das folgende Code-Snippet zeigt, wie Sie eine Liste mit demTransformingLazyColumn Layout erstellen, um Inhalte zu erstellen, die
auf verschiedenen Wear OS-Displaygrößen gut aussehen.
Das Snippet zeigt auch die Verwendung des Modifikators minimumVerticalContentPadding, den Sie für die Listenelemente festlegen sollten, um den richtigen Abstand oben und unten in der Liste anzuwenden.
Wenn Sie die Scrollanzeige sehen möchten, geben Sie columnState zwischen ScreenScaffold und TransformingLazyColumn frei:
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, ) } } } }
Snap-and-Fling-Effekt hinzufügen
Durch das Snapping wird sichergestellt, dass die Liste, wenn ein Nutzer eine Scroll- oder zügig wischen-Geste beendet, mit einem Element an einer bestimmten Stelle, in der Regel in der Mitte des Displays, anhält. Auf runden Displays, auf denen Elemente skaliert und morphing-animiert werden, wenn sie sich von der Mitte entfernen, ist das Snapping besonders nützlich, um sicherzustellen, dass das relevanteste Element im optimalen Betrachtungsbereich vollständig sichtbar und lesbar bleibt.Wenn Sie ein Snap-and-Fling-Verhalten hinzufügen möchten, legen Sie den Parameter flingBehavior auf TransformingLazyColumnDefaults.snapFlingBehavior(columnState) fest.
Legen Sie rotaryScrollableBehavior entsprechend fest, indem Sie RotaryScrollableDefaults.snapBehavior(columnState) verwenden, um eine einheitliche Nutzererfahrung bei Verwendung der physischen Krone oder Lünette zu gewährleisten.
val columnState = rememberTransformingLazyColumnState() ScreenScaffold(scrollState = columnState) { contentPadding -> TransformingLazyColumn( state = columnState, flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState), rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState) ) { // ... // ... } }
Umgekehrtes Layout
Standardmäßig wird eine scrollbare Liste am oberen Rand verankert. Wenn ein Nutzer bis zum Ende einer Standardliste gescrollt hat und ein neues Element hinzugefügt wird, bleibt die Ansicht des Nutzers auf dem aktuellen Element. Wenn der Nutzer beispielsweise Element 10 unten auf dem Display sieht und Element 11 hinzugefügt wird, bleibt die Ansicht auf Element 10 fokussiert und Element 11 wird unter der aktuellen Ansicht außerhalb des Displays angezeigt.
Für Anwendungsfälle wie Messaging-Apps oder Live-Logs ist dieses Verhalten in der Regel nicht erwünscht. Wenn neue Elemente eingehen, möchten Nutzer in der Regel die neuesten Inhalte sofort sehen, wenn sie sich bereits am Ende der Liste befinden. Wenn viele Elemente gleichzeitig eingehen, sollte die Liste zum neuesten Element unten springen. Das bedeutet, dass einige Elemente dazwischen möglicherweise gar nicht angezeigt werden, es sei denn, der Nutzer scrollt wieder nach oben.
Um diese Anwendungsfälle zu unterstützen, können Sie mit TransformingLazyColumn das Layout umkehren, indem Sie reverseLayout = true festlegen. Dadurch ändert sich der Anker der Liste vom oberen zum unteren Rand.
Wenn Sie reverseLayout = true festlegen, wird auch die visuelle Reihenfolge der Elemente und die Richtung der Scrollgesten umgekehrt:
- Elemente werden von unten nach oben zusammengesetzt. Das bedeutet, dass Index 0 unten auf dem Display angezeigt wird.
- Wenn Sie nach oben scrollen, werden Elemente mit höheren Indizes angezeigt.
Wenn Sie ein Snap-and-Fling-Verhalten zusammen mit einem umgekehrten Layout hinzufügen möchten, können Sie flingBehavior und rotaryScrollableBehavior wie im folgenden Snippet kombinieren:
val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold(scrollState = columnState) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding, reverseLayout = true, modifier = Modifier.fillMaxWidth() ) { items(10) { index -> Button( label = { Text( text = "Item ${index + 1}" ) }, onClick = {}, modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) } item { // With reverseLayout = true, the last item declared appears at the top. ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) { Text("Header") } } } }
Die folgenden Bilder zeigen den Unterschied zwischen einer normalen und einer umgekehrten Liste:
Randbuttons in Listen
Für Material 3 können Sie einen EdgeButton hinzufügen, einen Button, der am unteren Rand der Listen angebracht ist. Fügen Sie diesen jedoch nicht als Element in TransformingLazyColumn ein, sondern verwenden Sie den Slot edgeButton in ScreenScaffold.
Wenn Sie den Slot edgeButton verwenden, wird der Button korrekt am unteren Rand des Displays positioniert und verhält sich beim Scrollen der Liste entsprechend.
Das folgende Code-Snippet zeigt, wie Sie EdgeButton implementieren:
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, ) { // ... // ... } }
SwipeToReveal in Listen
Mit der Komponente SwipeToReveal können Sie durch Wischen auf Aktionen für ein Listenelement zugreifen, z. B. eine Card oder Chip. Durch Wischen werden in der Regel ein oder zwei Aktionsbuttons (z. B. „Löschen“ oder „Mehr“) von der Seite angezeigt.
Wenn Sie SwipeToReveal in einer TransformingLazyColumn verwenden, beachten Sie die folgenden Richtlinien:
- Beim Scrollen zurücksetzen: Wenn der Nutzer in der Liste scrollt, setzen Sie alle aufgewischten Elemente auf ihren verdeckten Zustand zurück.
- Einheitliche Höhen: Legen Sie die Höhen der Aktionsbuttons so fest, dass sie mit dem inneren
aufgewischten Element übereinstimmen (unabhängig davon, ob es sich um ein
Buttonoder eineCardhandelt), um ein einheitliches Erscheinungsbild zu gewährleisten. - Container transformieren: Wenden Sie den Modifikator
transformedHeightundtransformationSpecauf die KomponenteSwipeToRevealselbst an. - Nicht doppelt transformieren: Wenden Sie die Modifikatoren
transformedHeightodertransformationnicht auf das innere aufgewischte Element an (die Karte oder den Button im ContainerSwipeToReveal).
Empfehlungen für Sie
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist
- Codelab: Compose für Wear OS
- Listen und Raster
- Ansichten in Compose verwenden