Per le app TV, l'esperienza di navigazione si basa su una navigazione efficiente basata sullo stato attivo. Utilizzando i layout lazy standard di Compose Foundation, puoi creare elenchi verticali e orizzontali ad alte prestazioni che gestiscono automaticamente lo scorrimento basato sullo stato attivo per mantenere visibili gli elementi attivi.
Comportamento di scorrimento predefinito ottimizzato per la TV
A partire da Compose Foundation 1.7.0, i layout con caricamento lento standard (come LazyRow
e LazyColumn) includono il supporto integrato per le funzionalità di posizionamento dello stato attivo. Questo
è il modo consigliato per creare cataloghi per le app TV, in quanto aiuta a mantenere gli elementi
attivi visibili e posizionati in modo intuitivo per l'utente.
Per implementare un elenco scorrevole di base, utilizza i componenti lazy standard. Questi componenti gestiscono automaticamente la navigazione con il D-pad e mostrano l'elemento attivo.
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 */ } ) } } }
Personalizza il comportamento di scorrimento con BringIntoViewSpec
Se il tuo design richiede un punto di "pivot" specifico (ad esempio, mantenere l'elemento attivo esattamente al 30% dal bordo sinistro), puoi personalizzare il comportamento di scorrimento utilizzando un BringIntoViewSpec. Questa funzionalità sostituisce la precedente pivotOffsets
consentendoti di definire esattamente come deve scorrere l'area visibile
per adattarsi a un elemento attivo.
1. Definisci un BringIntoViewSpec personalizzato
Il seguente composable di supporto ti consente di definire un "pivot" in base alle frazioni principali e secondarie. parentFraction determina dove deve essere posizionato l'elemento nel container, mentre childFraction determina quale parte dell'elemento si allinea a quel punto.
@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. Applica la specifica personalizzata
Racchiudi i layout con l'helper per applicare il posizionamento. Questo è utile per creare una "linea di messa a fuoco coerente" tra le diverse righe del catalogo.
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. Disattivazione per layout nidificati specifici
Se hai un layout nidificato specifico che deve utilizzare il comportamento di scorrimento standard anziché il pivot personalizzato, fornisci 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 { /* ... */ } } } } }
In effetti, il passaggio di un BringIntoViewSpec vuoto consente di attivare il comportamento predefinito del framework.
Migrazione da TV Foundation a Compose Foundation
I layout lazy specifici per la TV in androidx.tv.foundation sono stati ritirati a favore dei layout standard di Compose Foundation.
Aggiornamenti delle dipendenze
Verifica che build.gradle utilizzi la versione 1.7.0 o successiva per:
androidx.compose.foundationandroidx.compose.runtime
Mappatura dei componenti
Per eseguire la migrazione, aggiorna le importazioni e rimuovi il prefisso Tv dai componenti:
| Componente TV ritirato | Sostituzione di Compose Foundation |
|---|---|
| TvLazyRow | LazyRow |
| TvLazyColumn | LazyColumn |
| TvLazyHorizontalGrid | LazyHorizontalGrid |
| TvLazyVerticalGrid | LazyVerticalGrid |
| pivotOffsets | BringIntoViewSpec (tramite LocalBringIntoViewSpec) |