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 projekt wymaga określonego punktu „obrotu” (np. utrzymania zaznaczonego elementu dokładnie 30% od lewej krawędzi), możesz dostosować przewijanie za pomocą BringIntoViewSpec. Zastępuje to starszą funkcję pivotOffsets, ponieważ umożliwia dokładne określenie, jak widoczny obszar ma się przewijać, aby dopasować się 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 do tworzenia „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 frameworka.
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) |