Pour les applications TV, l'expérience de navigation repose sur une navigation efficace basée sur le focus. À l'aide des mises en page Lazy Compose Foundation standards, vous pouvez créer des listes verticales et horizontales performantes qui gèrent automatiquement le défilement axé sur le focus pour que les éléments actifs restent visibles.
Comportement de défilement par défaut optimisé pour la TV
À partir de Compose Foundation 1.7.0, les mises en page Lazy standards (comme LazyRow et LazyColumn) sont compatibles avec les fonctionnalités de positionnement du focus. Il s'agit de la méthode recommandée pour créer des catalogues pour les applications TV, car elle permet de garder les éléments ciblés visibles et positionnés de manière intuitive pour l'utilisateur.
Pour implémenter une liste de défilement de base, utilisez les composants Lazy standards. Ces composants gèrent automatiquement la navigation avec le pavé directionnel et affichent l'élément ciblé.
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 */ }
)
}
}
}
Personnaliser le comportement de défilement avec BringIntoViewSpec
Si votre conception nécessite un point de "pivot" spécifique (par exemple, pour que l'élément ciblé soit exactement à 30 % du bord gauche), vous pouvez personnaliser le comportement de défilement à l'aide d'un BringIntoViewSpec. Cela remplace l'ancienne fonctionnalité pivotOffsets en vous permettant de définir exactement comment la fenêtre d'affichage doit défiler pour s'adapter à un élément ciblé.
1. Définir un BringIntoViewSpec personnalisé
Le composable d'assistance suivant vous permet de définir un "pivot" en fonction des fractions parent et enfant. Le parentFraction détermine l'endroit où l'élément doit atterrir dans le conteneur, et le childFraction détermine quelle partie de l'élément s'aligne sur ce point.
@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. Appliquer la spécification personnalisée
Encapsulez vos mises en page avec l'assistance pour appliquer le positionnement. Cela est utile pour créer une "ligne de focus cohérente" sur différentes lignes de votre catalogue.
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. Désactiver des mises en page imbriquées spécifiques
Si vous disposez d'une mise en page imbriquée spécifique qui doit utiliser un comportement de défilement standard au lieu de votre pivot personnalisé, fournissez le 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 { ... }
}
}
}
}
En effet, le fait de transmettre un BringIntoViewSpec vide permet au comportement par défaut du framework de prendre le relais.
Migration de TV Foundation vers Compose Foundation
Les mises en page Lazy spécifiques à la TV dans androidx.tv.foundation sont obsolètes au profit des mises en page Compose Foundation standards.
Mises à jour des dépendances
Vérifiez que votre build.gradle utilise la version 1.7.0 ou une version ultérieure pour les éléments suivants :
androidx.compose.foundationandroidx.compose.runtime
Mappage des composants
Pour effectuer la migration, mettez à jour vos importations et supprimez le préfixe Tv de vos composants :
| Composant TV obsolète | Remplacement Compose Foundation |
|---|---|
| TvLazyRow | LazyRow |
| TvLazyColumn | LazyColumn |
| TvLazyHorizontalGrid | LazyHorizontalGrid |
| TvLazyVerticalGrid | LazyVerticalGrid |
| pivotOffsets | BringIntoViewSpec (via LocalBringIntoViewSpec) |