Actualités sur les produits

Nouveautés de la version d'avril 2026 de Jetpack Compose

Temps de lecture : 5 min
Meghan Mehta
Developers Advocate, Android

La version d'avril 2026 de Jetpack Compose est désormais stable. Elle contient la version 1.11 des modules Compose de base (voir le mappage complet de la nomenclature), des outils de débogage des éléments partagés, des événements de pavé tactile et plus encore. Nous proposons également quelques API expérimentales que nous vous invitons à essayer et à nous faire part de vos commentaires.

Pour utiliser la version d'aujourd'hui, mettez à niveau votre version de la nomenclature Compose vers :

implementation(platform("androidx.compose:compose-bom:2026.04.01"))

Modifications apportées dans Compose 1.11.0

Exécution de coroutines dans les tests

Nous apportons une mise à jour majeure à la façon dont Compose gère la synchronisation des tests. Après la période d'activation annoncée dans Compose 1.10, les API de test v2 sont désormais celles par défaut, et les API v1 sont obsolètes. Le changement clé est le remplacement du coordinateur de test par défaut. Alors que les API v1 s'appuyaient sur le UnconfinedTestDispatcher, qui exécutait immédiatement les coroutines, les API v2 utilisent le StandardTestDispatcher. Cela signifie que lorsqu'une coroutine est lancée dans vos tests, elle est désormais mise en file d'attente et ne s'exécute que lorsque l'horloge virtuelle est avancée.

Cela imite mieux les conditions de production, ce qui permet d'éliminer efficacement les conditions de concurrence et de rendre votre suite de tests beaucoup plus robuste et moins instable.

Pour vous assurer que vos tests correspondent au comportement standard des coroutines et éviter les problèmes de compatibilité à l'avenir, nous vous recommandons vivement de migrer votre suite de tests. Consultez notre guide de migration complet pour obtenir des mappages d'API et des correctifs courants.

Améliorations des éléments partagés et outils d'animation

Nous avons également ajouté des outils de débogage visuel pratiques pour les éléments partagés et Modifier.animatedBounds. Vous pouvez désormais voir exactement ce qui se passe en arrière-plan (limites cibles, trajectoires d'animation et nombre de correspondances trouvées, par exemple), ce qui facilite grandement l'identification de la raison pour laquelle une transition peut ne pas se comporter comme prévu. Pour utiliser les nouveaux outils, il vous suffit d'entourer votre SharedTransitionLayout avec le LookaheadAnimationVisualDebugging composable. 

LookaheadAnimationVisualDebugging(
    overlayColor = Color(0x4AE91E63),
    isEnabled = true,
    multipleMatchesColor = Color.Green,
    isShowKeylabelEnabled = false,
    unmatchedElementColor = Color.Red,
) {
    SharedTransitionLayout {
        CompositionLocalProvider(
            LocalSharedTransitionScope provides this,
        ) {
            // your content
        }
    }
}

Événements de pavé tactile

Nous avons repensé la compatibilité de Compose avec les pavés tactiles, tels que les pavés tactiles intégrés aux ordinateurs portables, les pavés tactiles amovibles pour tablettes ou les pavés tactiles externes/virtuels. Les événements de pavé tactile de base seront désormais généralement considérés comme des événements PointerType.Mouse, ce qui aligne le comportement de la souris et du pavé tactile pour mieux répondre aux attentes des utilisateurs. Auparavant, ces événements de pavé tactile étaient interprétés comme de faux doigts d'écran tactile de PointerType.Touch, ce qui entraînait des expériences utilisateur déroutantes. Par exemple, cliquer et faire glisser avec un pavé tactile faisait défiler la page au lieu de sélectionner du texte. En modifiant le type de pointeur de ces événements dans la dernière version de Compose, cliquer et faire glisser avec un pavé tactile ne fera plus défiler la page.

Nous avons également ajouté la prise en charge de gestes de pavé tactile plus complexes reconnus par la plate-forme depuis l'API 34, y compris les balayages à deux doigts et les pincements. Ces gestes sont automatiquement reconnus par des composants tels que Modifier.scrollable et Modifier.transformable pour un meilleur comportement avec les pavés tactiles.

Ces modifications améliorent le comportement des pavés tactiles dans les composants intégrés, avec la suppression des marges de défilement tactiles redondantes, un geste de glisser-déposer plus intuitif, la sélection par double-clic et triple-clic dans les champs de texte, et des menus contextuels de style ordinateur dans les champs de texte.

Pour tester le comportement du pavé tactile, de nouvelles API de test avec performTrackpadInput, permettent de valider le comportement de vos applications lorsqu'elles sont utilisées avec un pavé tactile. Si vous disposez de détecteurs de gestes personnalisés, validez le comportement sur différents types d'entrée, y compris les écrans tactiles, les souris, les pavés tactiles et les stylets, et assurez la compatibilité avec les molettes de souris et les gestes de pavé tactile.

beforeAndAfter.webp

Valeurs par défaut de l'hôte de composition (environnement d'exécution Compose)

Nous avons introduit HostDefaultProviderLocalHostDefaultProviderHostDefaultKey, et ViewTreeHostDefaultKey pour fournir des services au niveau de l'hôte directement via compose-runtime. Cela évite aux bibliothèques de dépendre de compose-ui pour les recherches, ce qui améliore la compatibilité avec Kotlin Multiplatform. Pour lier ces valeurs à l'arborescence de composition, les auteurs de bibliothèques peuvent utiliser compositionLocalWithHostDefaultOf pour créer un CompositionLocal qui résout les valeurs par défaut de l'hôte.

Wrappers d'aperçu

Aperçus personnalisés d'Android Studio est une nouvelle fonctionnalité qui vous permet de définir exactement comment le contenu d'un aperçu Compose est affiché.

En implémentant l'interface PreviewWrapperProvider et en appliquant la nouvelle annotation @PreviewWrapper, vous pouvez facilement injecter une logique personnalisée, par exemple en appliquant un Theme spécifique. L'annotation peut être appliquée à une fonction annotée avec @Composable et @Preview ou @MultiPreview, offrant ainsi une solution générique et facile à utiliser qui fonctionne avec les fonctionnalités d'aperçu et réduit considérablement le code répétitif.

class ThemeWrapper: PreviewWrapper {
    @Composable
    override fun Wrap(content: @Composable (() -> Unit)) {
        JetsnackTheme {
            content()
        }
    }
}

@PreviewWrapperProvider(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
    // JetsnackTheme in effect
    Button(onClick = {}) {
        Text(text = "Demo")
    }
}

Obsolescence et suppression

  • Comme annoncé dans l' article de blog sur Compose 1.10, nous allons rendre Modifier.onFirstVisible() obsolète. Son nom a souvent donné lieu à des idées fausses, en particulier dans les mises en page différées, où il se déclenchait plusieurs fois lors du défilement. Nous vous recommandons de migrer vers Modifier.onVisibilityChanged(), qui permet un suivi manuel plus précis des états de visibilité adaptés aux exigences spécifiques de votre cas d'utilisation.
  • L'indicateur ComposeFoundationFlags.isTextFieldDpadNavigationEnabled a été supprimé, car la navigation par pavé directionnel pour les TextFields est désormais toujours activée par défaut. Le nouveau comportement garantit que les événements du pavé directionnel d'une manette de jeu ou d'une télécommande de télévision déplacent d'abord le curseur dans la direction donnée. La sélection ne peut passer à un autre élément que lorsque le curseur atteint la fin du texte.

API à venir

Dans la prochaine version 1.12.0 de Compose, compileSdk sera mis à niveau vers compileSdk 37, avec AGP 9, et toutes les applications et bibliothèques qui dépendent de Compose hériteront de cette exigence. Nous vous recommandons de vous tenir informé des dernières versions publiées, car Compose vise à adopter rapidement de nouveaux compileSdks pour fournir un accès aux dernières fonctionnalités Android. Pour en savoir plus sur la version d'AGP compatible avec les différents niveaux d'API, consultez la documentation ici

Dans Compose 1.11.0, les API suivantes sont introduites en tant que @Experimental, et nous sommes impatients de recevoir vos commentaires lorsque vous les explorerez dans vos applications. Notez que @Experimental APIs sont fournies pour une évaluation et des commentaires précoces, et qu'elles peuvent subir des modifications importantes ou être supprimées dans les futures versions.

Styles (expérimental)

Nous introduisons une nouvelle API de base expérimentale pour le style. L'API Style est un nouveau paradigme permettant de personnaliser les éléments visuels des composants, ce qui était traditionnellement effectué avec des modificateurs. Elle est conçue pour permettre une personnalisation plus approfondie et plus facile en exposant un ensemble standard de propriétés stylisables avec un style simple basé sur l'état et des transitions animées. Avec cette nouvelle API, nous constatons déjà des avantages prometteurs en termes de performances. Nous prévoyons d'adopter les styles dans les composants Material une fois que l'API Style sera stabilisée.

Voici un exemple de base de remplacement d'un arrière-plan de style d'état enfoncé :

@Composable
fun LoginButton(modifier: Modifier = Modifier) {
    Button(
        onClick = {
            // Login logic
        },
        modifier = modifier,
        style = {
            background(
                Brush.linearGradient(
                    listOf(lightPurple, lightBlue)
                )
            )
            width(75.dp)
            height(50.dp)
            textAlign(TextAlign.Center)
            externalPadding(16.dp)

            pressed {
                background(
                    Brush.linearGradient(
                        listOf(Color.Magenta, Color.Red)
                    )
                )
            }
        }
    ){
        Text(
            text = "Login",
        )
    }
}
styles.webp

Consultez la documentation et signalez les bugs ici.

MediaQuery (expérimental)

La nouvelle API mediaQuery offre un moyen déclaratif et performant d'adapter votre interface utilisateur à son environnement. Elle extrait la récupération d'informations complexes en conditions simples dans un UiMediaScope, ce qui garantit que la recomposition ne se produit que lorsque cela est nécessaire.

Grâce à la prise en charge d'un large éventail de signaux environnementaux (des fonctionnalités de l'appareil, comme les types de clavier et la précision du pointeur, aux états contextuels, comme la taille et la position de la fenêtre), vous pouvez créer des expériences très réactives. Les performances sont intégrées à derivedMediaQuery pour gérer les mises à jour à haute fréquence, tandis que la possibilité de remplacer les sélections permet de tester et de prévisualiser de manière transparente les configurations matérielles. Auparavant, pour accéder à certaines propriétés de l'appareil (par exemple, si un appareil était en mode Tabletop), vous deviez écrire beaucoup de code réutilisable : 

@Composable
fun isTabletopPosture(
    context: Context = LocalContext.current
): Boolean {
    val windowLayoutInfo by
        WindowInfoTracker
            .getOrCreate(context)
            .windowLayoutInfo(context)
            .collectAsStateWithLifecycle(null)

    return windowLayoutInfo.displayFeatures.any { displayFeature ->
        displayFeature is FoldingFeature &&
            displayFeature.state == FoldingFeature.State.HALF_OPENED &&
            displayFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
    }
}

@Composable
fun VideoPlayer() {
    if(isTabletopPosture()) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

Désormais, avec UIMediaQuery, vous pouvez ajouter la syntaxe mediaQuery pour interroger les propriétés de l'appareil, par exemple si un appareil est en mode Tabletop :

@OptIn(ExperimentalMediaQueryApi::class)
@Composable
fun VideoPlayer() {
    if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

Consultez la documentation et signalez les bugs ici.

Grid (expérimental)

Grid est une nouvelle API puissante permettant de créer des mises en page bidimensionnelles complexes dans Jetpack Compose. Alors que Row et Column sont idéaux pour les conceptions linéaires, Grid vous offre le contrôle structurel nécessaire pour l'architecture au niveau de l'écran et les composants complexes sans la surcharge d'une liste déroulante. Grid vous permet de définir votre mise en page à l'aide de pistes, d'espaces et de cellules, en proposant des options de dimensionnement familières telles que Dp, des pourcentages, des tailles de contenu intrinsèques et des unités "Fr" flexibles. 

@OptIn(ExperimentalGridApi::class)
@Composable
fun GridExample() {
    Grid(
        config = {
            repeat(4) { column(0.25f) }
            repeat(2) { row(0.5f) }
            gap(16.dp)
        }
    ) {
        Card1(modifier = Modifier.gridItem(rowSpan = 2)
        Card2(modifier = Modifier.gridItem(colmnSpan = 3)
        Card3(modifier = Modifier.gridItem(columnSpan = 2)
        Card4()
    }
}

Vous pouvez placer des éléments automatiquement ou les étendre explicitement sur plusieurs lignes et colonnes pour plus de précision. Mieux encore, il est hautement adaptatif : vous pouvez reconfigurer dynamiquement vos pistes et étendues de grille pour répondre aux états de l'appareil, comme le mode Tabletop ou les changements d'orientation, afin que votre interface utilisateur soit optimale sur tous les facteurs de forme.

Grid.gif

Consultez la documentation et signalez les bugs ici

FlexBox (expérimental)

FlexBox est un conteneur de mise en page conçu pour les interfaces utilisateur adaptatives et hautes performances. Il gère le dimensionnement des éléments et la répartition de l'espace en fonction des dimensions du conteneur disponibles.Il gère les tâches complexes telles que le retour à la ligne (wrap) et l'alignement multi-axes des éléments (justifyContent, alignItems, alignContent). Il permet aux éléments de s'agrandir (grow) ou de se réduire (shrink) pour remplir le conteneur. 

@OptIn(ExperimentalFlexBoxApi::class)
fun FlexBoxWrapping(){
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(8.dp)
        }
    ) {
        RedRoundedBox()
        BlueRoundedBox()
        GreenRoundedBox(modifier = Modifier.width(350.dp).flex { grow(1.0f) })
        OrangeRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.7f) })
        PinkRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.3f) })
    }
}
AnimationGif.gif

Consultez la documentation et signalez les bugs ici.

Nouvelle implémentation de SlotTable (expérimental)

Nous avons introduit une nouvelle implémentation de SlotTable, qui est désactivée par défaut dans cette version. SlotTable est la structure de données interne que l'environnement d'exécution Compose utilise pour suivre l'état de votre hiérarchie de composition, suivre les invalidations/recompositions, stocker les valeurs mémorisées et suivre toutes les métadonnées de la composition au moment de l'exécution. Cette nouvelle implémentation est conçue pour améliorer les performances, principalement en ce qui concerne les modifications aléatoires.

Pour essayer le nouveau SlotTable, activez ComposeRuntimeFlags.isLinkBufferComposerEnabled

Commencez à coder dès aujourd'hui !

Avec autant de nouvelles API intéressantes dans Jetpack Compose, et bien d'autres à venir, c'est le moment idéal pour migrer vers Jetpack Compose.Comme toujours, nous apprécions vos commentaires et vos demandes de fonctionnalités (en particulier sur les fonctionnalités @Experimental qui sont encore en cours de développement). Veuillez les signaler ici. À vos claviers !

Écrit par :

Lire la suite