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, während das Element durch den Bildschirm scrollt. - Verwenden Sie
transformation = SurfaceTransformation(transformationSpec), um die visuellen Effekte anzuwenden, einschließlich der Verkleinerung der Elementinhalte. - 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 Bildschirms nähert:
Das folgende Code-Snippet zeigt, wie Sie mit demTransformingLazyColumn Layout eine Liste erstellen, deren Inhalte 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 an:
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 Einrasten 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 Bildschirms, anhält. Auf runden Displays, auf denen Elemente skaliert und morphing-animiert werden, wenn sie sich von der Mitte entfernen, ist das Einrasten 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 der 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 Bildschirm 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 Bildschirms 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.
Zur Unterstützung dieser Anwendungsfälle 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, werden 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 Bildschirm 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 stattdessen den Slot edgeButton in ScreenScaffold.
Durch die Verwendung des Slots edgeButton wird sichergestellt, dass der Button korrekt am unteren Rand des Bildschirms positioniert ist und sich beim Scrollen der Liste richtig verhält.
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, ) { // ... // ... } }
„Zum Aufdecken wischen“ 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 in den 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