W przypadku aplikacji na telewizory przeglądanie opiera się na wydajnej nawigacji opartej na zaznaczaniu. Korzystając ze standardowych układów leniwych Compose Foundation, możesz tworzyć wydajne listy pionowe i poziome, które automatycznie obsługują przewijanie oparte na fokusie, aby aktywne elementy były widoczne.
Domyślne zachowanie przewijania zoptymalizowane pod kątem telewizorów
Od wersji 1.7.0 biblioteki Compose Foundation standardowe układy leniwe (np. LazyRow i LazyColumn) mają wbudowaną obsługę funkcji pozycjonowania fokusu. Jest to zalecany sposób tworzenia katalogów aplikacji na telewizory, ponieważ pomaga utrzymać widoczność elementów, na których skupia się uwaga użytkownika, i intuicyjnie je pozycjonować.
Aby wdrożyć podstawową listę z możliwością przewijania, użyj standardowych komponentów leniwych. Te komponenty automatycznie obsługują nawigację za pomocą pada kierunkowego i wyświetlają zaznaczony element.
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 */ }
)
}
}
}
Dostosowywanie przewijania za pomocą BringIntoViewSpec
Jeśli Twój projekt wymaga określonego punktu „obrotu” (np. utrzymania zaznaczonego elementu dokładnie 30% od lewej krawędzi), możesz dostosować zachowanie przewijania za pomocą BringIntoViewSpec. Zastępuje to starszą funkcję pivotOffsets, ponieważ umożliwia dokładne określenie sposobu przewijania widocznego obszaru w celu dopasowania go do zaznaczonego elementu.
1. Definiowanie niestandardowego celu BringIntoViewSpec
Poniższy komponent kompozycyjny pomocniczy umożliwia zdefiniowanie „punktu obrotu” na podstawie ułamków nadrzędnych i podrzędnych. Atrybut parentFraction określa, w którym miejscu kontenera ma się znaleźć element, a atrybut childFraction określa, która część elementu ma być wyrównana do tego punktu.
@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. Zastosuj specyfikację niestandardową
Aby zastosować pozycjonowanie, umieść układy w funkcji pomocniczej. Jest to przydatne przy tworzeniu „spójnej linii ostrości” w różnych wierszach katalogu.
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. Rezygnacja z określonych zagnieżdżonych układów
Jeśli masz konkretny zagnieżdżony układ, który powinien używać standardowego przewijania zamiast niestandardowego obrotu, podaj DefaultBringIntoViewSpec:
private val DefaultBringIntoViewSpec = object : BringIntoViewSpec {}
PositionFocusedItemInLazyLayout {
LazyColumn {
item {
// This row will ignore the custom pivot and use default behavior
CompositionLocalProvider(LocalBringIntoViewSpec provides DefaultBringIntoViewSpec) {
LazyRow { ... }
}
}
}
}
Przekazanie pustego parametru BringIntoViewSpec powoduje przejęcie domyślnego zachowania platformy.
Migracja z TV Foundation do Compose Foundation
Układy leniwe specyficzne dla telewizorów w androidx.tv.foundation zostały wycofane na rzecz standardowych układów Compose Foundation.
Aktualizacje zależności
Sprawdź, czy build.gradle używa wersji 1.7.0 lub nowszej w przypadku:
androidx.compose.foundationandroidx.compose.runtime
Mapowanie komponentów
Aby przeprowadzić migrację, zaktualizuj importy i usuń prefiks Tv z komponentów:
| Wycofany komponent telewizyjny | Compose Foundation replacement |
|---|---|
| TvLazyRow | LazyRow |
| TvLazyColumn | LazyColumn |
| TvLazyHorizontalGrid | LazyHorizontalGrid |
| TvLazyVerticalGrid | LazyVerticalGrid |
| pivotOffsets | BringIntoViewSpec (przez LocalBringIntoViewSpec) |