Actualités sur les produits

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

Temps de lecture : 6 min
Voir le profil de Meghan Mehta
Meghan Mehta Developer Advocate, Android

Aujourd'hui, la version d'avril 2026 de Jetpack Compose est stable. Cette version contient la version 1.11 des modules Compose principaux (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 à tester et à commenter.

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 à Compose 1.11.0

Exécution de coroutines dans les tests

Nous apportons une mise à jour importante à la façon dont Compose gère le timing des tests. Après la période d'activation annoncée dans Compose 1.10, les API de test v2 sont désormais utilisées par défaut, et les API v1 sont obsolètes. Le principal changement concerne le coordinateur de test par défaut. Alors que les API v1 s'appuyaient sur UnconfinedTestDispatcher, qui exécutait immédiatement les coroutines, les API v2 utilisent 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 pas tant que l'horloge virtuelle n'est pas avancée.

Cela permet de mieux imiter les conditions de production, 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 sont conformes au comportement standard des coroutines et éviter de futurs problèmes de compatibilité, nous vous recommandons vivement de migrer votre suite de tests. Consultez notre guide de migration complet pour découvrir les mappages d'API et les corrections courantes.

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

Nous avons également ajouté des outils de débogage visuels pratiques pour les éléments partagés et Modifier.animatedBounds. Vous pouvez désormais voir exactement ce qui se passe en arrière-plan (par exemple, les limites de la cible, les trajectoires d'animation et le nombre de correspondances trouvées), ce qui vous permet d'identifier beaucoup plus facilement pourquoi une transition ne se comporte pas comme prévu. Pour utiliser les nouveaux outils, il vous suffit d'encapsuler votre SharedTransitionLayout dans le composable LookaheadAnimationVisualDebugging. 

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

Événements du 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 base du pavé tactile seront désormais généralement considérés comme des événements PointerType.Mouse, ce qui alignera 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 sur l'é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 l'écran.

Nous avons également ajouté la prise en charge de gestes plus complexes sur le pavé tactile, 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 améliorer le comportement avec les pavés tactiles.

Ces modifications améliorent le comportement des pavés tactiles sur les composants intégrés, avec la suppression de la tolérance tactile redondante, un geste de démarrage du 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 bureau dans les champs de texte.

Pour tester le comportement du pavé tactile, de nouvelles API de test sont disponibles avec performTrackpadInput,. Elles 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ées, y compris les écrans tactiles, les souris, les pavés tactiles et les stylets, et assurez-vous de la compatibilité avec les molettes de souris et les gestes sur pavé tactile.

beforeAndAfter.webp

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

Nous avons introduit HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey et ViewTreeHostDefaultKey pour fournir des services au niveau de l'hôte directement via compose-runtime. Les bibliothèques n'ont donc plus besoin de dépendre de compose-ui pour les recherches, ce qui améliore la compatibilité avec Kotlin Multiplatform. Pour associer 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

Les aperçus personnalisés d'Android Studio sont 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 une solution générique et facile à utiliser qui fonctionne sur toutes les fonctionnalités en preview et réduit considérablement le code répétitif.

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


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

Fonctionnalités obsolètes et supprimées

  • Comme annoncé dans l'article de blog sur Compose 1.10, nous abandonnons Modifier.onFirstVisible(). Son nom entraînait souvent des malentendus, 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é aux exigences de votre cas d'utilisation spécifique.
  • Le flag ComposeFoundationFlags.isTextFieldDpadNavigationEnabled a été supprimé, car la navigation par pavé directionnel pour 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 TV 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 de Compose 1.12.0, compileSdk sera mis à niveau vers compileSdk 37, avec AGP 9. 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 les nouvelles versions de compileSdks pour donner accès aux dernières fonctionnalités d'Android. Pour en savoir plus sur la version d'AGP compatible avec les différents niveaux d'API, consultez cette documentation. 

Dans Compose 1.11.0, les API suivantes sont introduites en tant que @Experimental. Nous attendons avec impatience vos commentaires lorsque vous les explorerez dans vos applications. Notez que les @Experimental APIs sont fournis pour une évaluation et des commentaires précoces, et qu'ils peuvent subir des modifications importantes ou être supprimés dans les prochaines versions.

Styles (expérimental)

Nous lançons une nouvelle API de base expérimentale pour l'application de styles. L'API Style est un nouveau paradigme permettant de personnaliser les éléments visuels des composants, ce qui était traditionnellement effectué avec des modificateurs. Il est conçu pour permettre une personnalisation plus poussée et plus simple 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 simple 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 UI à son environnement. Il extrait la récupération d'informations complexes dans des conditions simples au sein d'un UiMediaScope, ce qui garantit que la recomposition ne se produit que lorsque cela est nécessaire.

Grâce à la compatibilité avec un large éventail de signaux environnementaux (des fonctionnalités de l'appareil, comme les types de claviers et la précision du pointeur, aux états contextuels, comme la taille de la fenêtre et la posture), vous pouvez créer des expériences hautement responsives. Les performances sont intégrées à derivedMediaQuery pour gérer les mises à jour à haute fréquence, tandis que la possibilité de remplacer les champs d'application permet de tester et de prévisualiser les configurations matérielles de manière fluide. Auparavant, pour accéder à certaines propriétés de l'appareil (par exemple, pour savoir si un appareil était en mode sur table), vous deviez écrire beaucoup de code standard : 

@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 pour savoir s'il est en mode sur table :

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

Consultez la documentation et signalez les bugs ici.

Grille (expérimental)

Grid est une nouvelle API puissante permettant de créer des mises en page bidimensionnelles complexes dans Jetpack Compose. Bien que Row et Column soient parfaits 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, et propose 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, elle est hautement adaptative : vous pouvez reconfigurer de manière dynamique les pistes et les étendues de votre grille pour répondre aux états de l'appareil, comme le mode sur table ou les changements d'orientation, afin que votre UI s'affiche correctement 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 des interfaces utilisateur adaptatives et hautes performances. Il gère la taille des éléments et la répartition de l'espace en fonction des dimensions du conteneur disponible. Il gère des tâches complexes telles que le retour à la ligne (wrap) et l'alignement multi-axe 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érimentale)

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 envoyer ici. À vos claviers !

Written by:
Continuer la lecture