Bei TV-Apps basiert die Navigation auf einer effizienten Fokusnavigation. Mit den standardmäßigen Lazy-Layouts von Compose Foundation können Sie leistungsstarke vertikale und horizontale Listen erstellen, bei denen das fokussierte Scrollen automatisch erfolgt, damit aktive Elemente im Blick bleiben.
Standardmäßiges Scrollverhalten, das für die TV-Wiedergabe optimiert ist
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 sie dazu beiträgt, dass fokussierte Elemente sichtbar bleiben und intuitiv für den Nutzer positioniert werden.
Verwenden Sie die Standard-Lazy-Komponenten, um eine einfache scrollbare Liste zu implementieren. Diese Komponenten übernehmen automatisch die Navigation mit dem Steuerkreuz und bringen das fokussierte Element in den Blick.
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. wenn das fokussierte Element genau 30% vom linken Rand entfernt sein soll, können Sie das Scrollverhalten mit einem BringIntoViewSpec anpassen. Diese Funktion ersetzt die ältere pivotOffsets-Funktion. Sie können damit genau festlegen, wie der Viewport gescrollt werden soll, um ein fokussiertes Element zu berücksichtigen.
1. Benutzerdefiniertes BringIntoViewSpec definieren
Mit dem folgenden Helper-Composable können Sie einen „Pivot“ basierend auf den Anteilen von über- und untergeordneten Elementen definieren. Mit parentFraction wird festgelegt, wo im Container das Element platziert werden soll, und mit childFraction wird bestimmt, welcher Teil des Elements mit 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
Umschließen Sie Ihre Layouts mit dem Helfer, um die Positionierung anzuwenden. Das ist nützlich, um in verschiedenen Zeilen Ihres Katalogs eine „einheitliche Fokuslinie“ 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 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 ein leeres BringIntoViewSpec übergeben, wird das Standardverhalten des Frameworks aktiviert.
Migration von TV Foundation zu Compose Foundation
Die TV-spezifischen Lazy-Layouts in androidx.tv.foundation werden zugunsten der Standard-Compose Foundation-Layouts eingestellt.
Abhängigkeitsupdates
Prüfen Sie, ob in Ihrer build.gradle Version 1.7.0 oder höher für Folgendes verwendet wird:
androidx.compose.foundationandroidx.compose.runtime
Komponentenzuordnung
Aktualisieren Sie zum Migrieren Ihre Importe und entfernen Sie das Präfix Tv aus Ihren Komponenten:
| Eingestellte TV-Komponente | Compose Foundation-Ersatz |
|---|---|
| TvLazyRow | LazyRow |
| TvLazyColumn | LazyColumn |
| TvLazyHorizontalGrid | LazyHorizontalGrid |
| TvLazyVerticalGrid | LazyVerticalGrid |
| pivotOffsets | BringIntoViewSpec (über LocalBringIntoViewSpec) |