Bei TV-Apps basiert das Surfen auf einer effizienten, fokusbasierten Navigation. Mit den standardmäßigen Lazy Layouts von Compose Foundation können Sie leistungsstarke vertikale und horizontale Listen erstellen, die automatisch das fokusgesteuerte Scrollen verarbeiten, damit aktive Elemente im Blick bleiben.
Standard-Scrollverhalten für Fernseher optimiert
Ab Compose Foundation 1.7.0 bieten standardmäßige Lazy Layouts (wie LazyRow und LazyColumn) integrierte Unterstützung für Funktionen zur Fokuspositionierung. Dies ist die empfohlene Methode zum Erstellen von Katalogen für TV-Apps, da so fokussierte Elemente sichtbar bleiben und für den Nutzer intuitiv positioniert werden.
Wenn Sie eine einfache scrollbare Liste implementieren möchten, verwenden Sie die standardmäßigen Lazy-Komponenten. Diese Komponenten übernehmen automatisch die Navigation über das Steuerkreuz und rücken das fokussierte Element in den Vordergrund.
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items @Composable fun MovieCatalog(movies: List<Movie>) { LazyRow { items(movies) { movie -> MovieCard( movie = movie, onClick = { /* Handle click */ } ) } } }
Scrollverhalten mit BringIntoViewSpec anpassen
Wenn Ihr Design einen bestimmten „Drehpunkt“ erfordert (z. B. dass das fokussierte Element genau 30% vom linken Rand entfernt bleibt), können Sie das Scrollverhalten mit einem BringIntoViewSpec anpassen. Diese Funktion ersetzt die ältere pivotOffsets-Funktion, da Sie genau festlegen können, wie der Darstellungsbereich gescrollt werden soll, um ein fokussiertes Element zu berücksichtigen.
1. Benutzerdefinierten BringIntoViewSpec definieren
Mit der folgenden komponierbaren Funktion können Sie einen „Pivot“ basierend auf übergeordneten und untergeordneten Bruchteilen definieren. Der parentFraction bestimmt, wo im Container das Element platziert werden soll, und der childFraction bestimmt, welcher Teil des Elements an diesem Punkt ausgerichtet wird.
@OptIn(ExperimentalFoundationApi::class) @Composable fun PositionFocusedItemInLazyLayout( parentFraction: Float = 0.3f, childFraction: Float = 0f, content: @Composable () -> Unit, ) { val bringIntoViewSpec = remember(parentFraction, childFraction) { object : BringIntoViewSpec { override fun calculateScrollDistance( offset: Float, // Item's initial position size: Float, // Item's size containerSize: Float // Container's size ): Float { // Calculate the offset position of the item's leading edge. val initialTargetForLeadingEdge = parentFraction * containerSize - (childFraction * size) // If the item fits in the container, and scrolling would cause // its trailing edge to be clipped, adjust targetForLeadingEdge // to prevent over-scrolling near the end of list. val targetForLeadingEdge = if (size <= containerSize && (containerSize - initialTargetForLeadingEdge) < size) { // If clipped, align the item's trailing edge with the // container's trailing edge. containerSize - size } else { initialTargetForLeadingEdge } // Return scroll distance relative to initial item position. return offset - targetForLeadingEdge } } } // Apply the spec to all scrollables in the hierarchy CompositionLocalProvider( LocalBringIntoViewSpec provides bringIntoViewSpec, content = content, ) }
2. Benutzerdefinierte Spezifikation anwenden
Verwenden Sie den Helper, um die Positionierung auf Ihre Layouts anzuwenden. Dies ist nützlich, um eine „konsistente Fokuslinie“ über verschiedene Zeilen Ihres Katalogs hinweg zu erstellen.
PositionFocusedItemInLazyLayout( parentFraction = 0.3f, // Pivot 30% from the edge childFraction = 0.5f // Center of the item aligns with the pivot ) { LazyColumn { items(sectionList) { section -> // This row and its items will respect the 30% pivot LazyRow { /* ... */ } } } }
3. Deaktivierung für bestimmte verschachtelte Layouts
Wenn Sie ein bestimmtes verschachteltes Layout haben, das das Standard-Scrollverhalten anstelle Ihres benutzerdefinierten Pivots verwenden soll, geben Sie den DefaultBringIntoViewSpec an:
private val DefaultBringIntoViewSpec = object : BringIntoViewSpec {} PositionFocusedItemInLazyLayout { LazyColumn { item { // This row will ignore the custom pivot and use default behavior CompositionLocalProvider(LocalBringIntoViewSpec provides DefaultBringIntoViewSpec) { LazyRow { /* ... */ } } } } }
Wenn Sie einen leeren BringIntoViewSpec übergeben, wird das Standardverhalten des Frameworks übernommen.
Migration von TV Foundation zu Compose Foundation
Die TV-spezifischen Lazy-Layouts in androidx.tv.foundation wurden zugunsten der Standard-Compose Foundation-Layouts eingestellt.
Abhängigkeitsupdates
Prüfen Sie, ob Ihre build.gradle Version 1.7.0 oder höher für Folgendes verwendet:
androidx.compose.foundationandroidx.compose.runtime
Komponentenzuordnung
Aktualisieren Sie für die Migration Ihre Importe und entfernen Sie das Präfix Tv aus Ihren Komponenten:
| Eingestellte TV-Komponente | Ersatz für Compose Foundation |
|---|---|
| TvLazyRow | LazyRow |
| TvLazyColumn | LazyColumn |
| TvLazyHorizontalGrid | LazyHorizontalGrid |
| TvLazyVerticalGrid | LazyVerticalGrid |
| pivotOffsets | BringIntoViewSpec (über LocalBringIntoViewSpec) |