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 zachować widoczność elementów, na których skupia się uwaga, 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ą element, na którym jest fokus.
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ć zachowanie przewijania za pomocą BringIntoViewSpec. Zastępuje to starszą funkcję pivotOffsets, ponieważ pozwala dokładnie określić, jak widoczny obszar ma się przewijać, aby dopasować się do elementu, na którym jest fokus.
1. Definiowanie niestandardowego BringIntoViewSpec
Poniższy komponent pomocniczy umożliwia zdefiniowanie „punktu obrotu” na podstawie ułamków nadrzędnych i podrzędnych. Atrybut parentFraction określa, gdzie w kontenerze 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. Stosowanie specyfikacji niestandardowej
Owiń układy za pomocą funkcji pomocniczej, aby zastosować pozycjonowanie. 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) |