Actualités des produits

Nouveautés de la version d'août 2026 de Jetpack Compose

Temps de lecture : 5 minutes
Afficher le profil de Nick Butcher
Nick Butcher Responsable produit

Aujourd'hui, la version d'août 2026 de Jetpack Compose est stable. Cette version apporte la version 1.12 aux modules Compose de base (voir le mappage complet de la nomenclature), en introduisant des API visuelles enrichies telles que les dégradés maillés et la prise en charge de la gamme de couleurs étendue (WCG), des fonctionnalités de mise en page structurelle telles que les zones nommées dans Grid, une intégration fluide avec le Gestionnaire d'identifiants d'Android, ainsi que des améliorations significatives en termes de tests et de performances.

Pour mettre à jour votre projet vers la version d'aujourd'hui, mettez à niveau votre version de la nomenclature Compose vers 2026.08.00 :

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

Modifications destructives

  • AGP et SDK de compilation : Compose 1.12 met à jour compileSdk vers l'API 37, ce qui nécessite au minimum AGP 9.1.2. Pour rappel, Compose ciblera toujours le dernier compileSdk. Pour en savoir plus sur cette modification, cliquez ici.
  • Modifier.onFirstVisible() est obsolète : migrez vers Modifier.onVisibilityChanged(), qui fournit un suivi plus précis du seuil de visibilité.

Graphismes

Dégradés maillés

Compose 1.12 introduit MeshGradientPainter pour vous aider à créer des dégradés de couleurs organiques multipoints.

meshGradient.gif
val rows = 1
val columns = 1

val gradientPainter = remember {
    MeshGradientPainter(rows, columns) {
        // Parameters: row, column, position, color
        setVertex(0, 0, Offset(0f, 0f), Color.Red)     // Top-Left
        setVertex(0, 1, Offset(1f, 0f), Color.Blue)    // Top-Right
        setVertex(1, 0, Offset(0f, 1f), Color.Green)   // Bottom-Left
        setVertex(1, 1, Offset(1f, 1f), Color.Yellow)  // Bottom-Right
    }
}

Box(
    modifier = modifier
        .aspectRatio(16/9f)
        .fillMaxWidth()
        .paint(gradientPainter)
)

Pour en savoir plus et obtenir des exemples, consultez la documentation.

Prise en charge de la gamme de couleurs étendue et de la HDR

Les écrans modernes offrent une fidélité des couleurs étendue et une plage dynamique plus élevée. Dans Compose 1.12, la prise en charge complète du pipeline pour la gamme de couleurs étendue (P3) et le rendu HDR a été activée dans les graphismes, la peinture et les shaders Compose. Les couleurs définies dans des espaces colorimétriques non sRVB (tels que Display P3) sont conservées jusqu'au rendu de la plate-forme sans écrêtage des couleurs. Les couleurs reviendront en toute sécurité au sRVB si elles utilisent un espace colorimétrique non compatible (par exemple, CieXyz, CieLab ou Oklab), si elles s'appuient sur un espace colorimétrique sur une version d'Android non compatible (par exemple, Bt2020Hlg sur Android 13 et versions antérieures) ou si l'application s'exécute sur Android 9 (API 28) et versions antérieures.

Autres changements notables :

  • LayerOutsets a été ajouté à GraphicsLayerModifier.graphicsLayer, que vous pouvez utiliser pour augmenter les limites visuelles du calque au-delà de sa taille mesurée. Appliquez LayerOutsets pour éviter le comportement clipToBounds implicite lorsque le calque est promu dans un tampon hors écran.

Styles

Lors de Google I/O, nous avons partagé notre vision initiale de l'API Styles Compose , une méthode unifiée et performante pour styliser les composants. Depuis, nous avons continué à développer l'architecture sous-jacente pour garantir une sûreté du typage stricte et une exactitude prévisible, et pour prendre en charge la création de systèmes de conception personnalisés. 

Pour nous assurer que cette couche de base est correcte, l'API restera expérimentale et vous pouvez vous attendre à des modifications destructives. 

Optimisations de l'environnement d'exécution

Surcharge SideEffect avec clé

SideEffect est désormais compatible avec les arguments clés, ce qui vous permet de déclencher des effets secondaires ponctuels chaque fois que des clés spécifiques changent. Cela peut améliorer les performances par rapport à l'utilisation d'un LaunchedEffect ou d'un DisposableEffect lorsque vous n'avez pas besoin de la coroutine ni du bloc de suppression. SideEffect est jusqu'à 90% plus rapide que LaunchedEffect et environ 20% plus rapide que DisposableEffect. Notez que SideEffect exécute son effet avant DisposableEffect et LaunchedEffect. Soyez donc prudent si vous migrez des effets existants vers cette API, en particulier pour les LaunchedEffects qui doivent être envoyés pour démarrer une fois le frame actuel terminé.

@Composable
fun AnalyticsTracker(userId: String, screenName: String) {
    SideEffect(key1 = userId, key2 = screenName) {
        analytics.logScreenView(userId, screenName)
    }
}

Animation

Transitions interactives en deux étapes

  • Nouveaux composables : DeferredAnimatedContent et DeferredAnimatedVisibility permettent de créer des transitions en deux étapes agréables, par exemple pour la prévisualisation du geste Retour.
  • Contrôle manuel de l'animation : pendant la phase différée d'une transition, les propriétés animées (comme l'échelle ou le décalage) peuvent désormais être manipulées manuellement en temps réel (par exemple, le suivi d'un geste de balayage).
  • Transfert fluide : une fois la phase différée terminée, le moteur de transition prend le relais et effectue un transfert fluide, y compris le transfert de vitesse, vers la transition automatique.
  • Prise en charge des éléments partagés : un nouveau indicateur permitTransformDuringDeferredTransition dans SharedContentConfig contrôle si les éléments partagés se transforment visuellement avec leurs conteneurs parents pendant la phase de transition différée.
val state = remember { DeferredTransitionState(initialScreen) }
val transition = rememberDeferredTransition(state)

if (predictiveBackInProgress) {
    state.defer(targetScreen)
} else {
    state.animateTo(targetScreen)
}

transition.DeferredAnimatedContent(
    targetState = targetScreen,
    mutableTransformSpec = {
       MutableContentTransform {
           // Manually manipulate properties during the deferred phase
           initialContentTransform { scale = swipeProgress }
       }
    }
) { screen ->
    ScreenContent(screen)
}

Vous trouverez ci-dessous deux démonstrations de cas d'utilisation dans lesquels une animation pilotée par un geste est transférée vers une animation déclenchée :

colorCards.gif

Texte, saisie et intégrations de plates-formes

Mise en forme de texte modifiable

De nouvelles API offrent une mise en forme de texte enrichi pour le texte modifiable dans BasicTextField. Vous pouvez désormais appliquer et manipuler par programmation la mise en forme des caractères et des paragraphes en ligne à l'aide de SpanStyle et ParagraphStyle via la nouvelle méthode addStyle() dans un champ TextFieldBuffer (par exemple, dans textFieldState.edit { ... } ou une InputTransformation). De plus, TextFieldBuffer fournit des API getSpanStyles() et getParagraphStyles() qui renvoient des objets TrackedRange, ce qui vous permet de lire, de mettre à jour ou de supprimer les styles appliqués. Pour compléter la création de la mise en forme, TextFieldState expose désormais une propriété textStyles en lecture seule pour interroger les styles actifs sur différentes plages, tandis que TextFieldBuffer fournit originalTextStyles pour inspecter l'état de la mise en forme avant une modification. La mise en forme du texte et les annotations personnalisées sont conservées lors des modifications de configuration.

val state = rememberTextFieldState("Formatted text in Compose 1.12")

// Apply bold and color styles to a range of text
state.edit {
    addStyle(
        SpanStyle(fontWeight = FontWeight.Bold, color = Color.Blue),
        start = 0,
        end = 9
    )
}

// Query active styles from TextFieldState
val currentStyles = state.textStyles

Sélection de texte

Une nouvelle SelectionState API fournit un contrôle et une observabilité programmatiques sur la sélection de texte dans un SelectionContainer. L'hébergement d'un objet SelectionState via rememberSelectionState() et sa transmission à SelectionContainer expose selectedTexts en tant que liste réactive de AnnotatedStrings et fournit des méthodes telles que selectAll(), clear(), select(TextRange) et extendSelectionByWord().

De plus, utilisez getSelectableTexts() pour récupérer tous les éléments de texte sélectionnables dans l'ordre de mise en page et sélectionner du texte dans les composables du SelectionContainer à l'aide d'une plage globale. 

@Composable
fun ProgrammaticSelectionExample() {
    val selectionState = rememberSelectionState()

    Column {
        Button(
            onClick = { selectionState.selectAll() },
            modifier = Modifier.disableSelectionClearOnTap()
        ) {
            Text("Select All")
        }

        SelectionContainer(state = selectionState) {
            Text("Text content to be selected programmatically.")
        }
    }
}

Intégration du Gestionnaire d'identifiants

Les champs de texte Compose s'intègrent désormais de manière native au Gestionnaire d'identifiants d'Android (API 34 et versions ultérieures) via le framework de saisie automatique (les versions antérieures à l'API 34 sont gérées par androidx.credentials library). En associant la nouvelle propriété sémantique credentialRequest à CredentialRequestData, les entrées de texte peuvent inviter à utiliser des clés d'accès, des identifiants enregistrés ou des demandes de connexion directement dans le flux d'entrée utilisateur.

@Composable
fun LoginField(textFieldState: TextFieldState) {
    val credentialData = remember {
        CredentialRequestData(
            // Specify Credential Manager request options
        )
    }

    BasicTextField(
        state = textFieldState,
        modifier = Modifier.semantics {
            credentialRequest = credentialData
        }
    )
}

Autres changements notables :

  • Prise en charge des paramètres de variation de police dans les polices téléchargeables.
  • Défilement automatique activé lors du glissement de la sélection de texte au-delà de la fenêtre d'affichage dans SelectionContainer.
  • Ajout de la prise en charge des sons d'interaction automatiques (clics et navigation par focus) aux composants Compose, avec un nouveau SoundEffectOnInteraction composable pour permettre la désactivation. Notez qu'en raison de cette modification, les écouteurs de clics sémantiques doivent désormais être appelés à partir du thread principal, ce qui peut affecter un petit nombre de cas de test.
  • KeyboardType inclut désormais DateTimeDateTime, et SignedDecimal.
  • BasicSecureTextField utilise désormais TextObfuscationMode.System par défaut, tandis que RevealLastTyped sert de remplacement absolu.

Améliorations de la mise en page

Zones nommées dans la mise en page en grille

La création de mises en page 2D complexes est désormais plus facile grâce aux zones nommées dans le @Experimental composant Grid. Plutôt que de gérer les indices numériques de colonnes et de lignes dans les éléments, vous pouvez définir des régions sémantiques dans votre GridConfigurationScope et positionner les composables par nom de zone.

@OptIn(ExperimentalGridApi::class)
@Composable
fun DashboardLayout() {
    Grid(
        config = {
            area("header", row = 0, column = 0, rowSpan = 1, columnSpan = 2)
            area("sidebar", row = 1, column = 0)
            area("content", row = 1, column = 1)
            gap(16.dp)
        }
    ) {
        HeaderSection(modifier = Modifier.gridItem(areaId = "header"))
        NavigationSidebar(modifier = Modifier.gridItem(areaId = "sidebar"))
        MainContentView(modifier = Modifier.gridItem(areaId = "content"))
    }
}

Pour en savoir plus, consultez la documentation.

Performances

Comme pour chaque version, nous continuons d'investir dans les performances de Compose pour nous assurer que le framework vous aide à créer des applications esthétiques et performantes. Dans cette version, nous nous sommes concentrés sur l'amélioration des performances de démarrage et nous constatons désormais un temps d'affichage initial (temps nécessaire à une application pour produire son premier frame) comparable à celui des vues dans nos benchmarks.

timetoinitialdisplay@2x _v2.png

Améliorations des tests et des outils

Synchronisation des tests

Compose 1.12 introduit de nouvelles API de test conçues pour réduire les temps d'exécution des tests et éliminer les instabilités lors de l'échantillonnage d'état :

  • hasPendingWork : vérifie passivement si l'interface utilisateur a du travail en attente sans faire avancer l'horloge, ce qui est idéal pour les boucles d'animation manuelles.
  • runWithoutImplicitWait : désactive temporairement la synchronisation implicite lors du passage par les frames d'horloge manuels (par exemple, les tests d'animation).
@Test
fun testAnimationStateFast() {

composeTestRule.mainClock.autoAdvance = false
    
    while (composeTestRule.hasPendingWork()) {
        composeTestRule.mainClock.advanceTimeByFrame()
        composeTestRule.waitForIdle()
        
        composeTestRule.runOnUiThread {
            composeTestRule.runWithoutImplicitWait {
                // This is most effective when querying multiple nodes in a single frame. 
                // It prevents the redundant synchronization overhead that would 
                // otherwise occur on every individual query.
                val box1 = composeTestRule.onNodeWithTag("Box1").fetchSemanticsNode()
                val box2 = composeTestRule.onNodeWithTag("Box2").fetchSemanticsNode()
                
                assertThat(box1.boundsInRoot.right).isAtMost(box2.boundsInRoot.left)
            }
        }
    }
}

Autres changements notables :

  • L'API captureToImage vous permet désormais de capturer une fenêtre pop-up ou une boîte de dialogue avec son ancre dans un seul bitmap.
  • Ajout de onRootWithViewInteraction pour limiter les recherches sémantiques Compose à des vues Android spécifiques. Cela simplifie le test des interfaces utilisateur hybrides, telles que les RecyclerViews, sans nécessiter de tags de test uniques dans le code de production.
  • @PreviewWrapper annotations peuvent désormais être appliquées à des classes @MultiPreview personnalisées, ce qui permet de réutiliser des configurations d'aperçu (telles que des thèmes personnalisés) dans plusieurs composants.

À vos claviers !

Compose 1.12 facilite et rend plus expressive que jamais la création d'applications, grâce aux dégradés maillés, à la prise en charge de la gamme de couleurs étendue, aux polices variables téléchargeables, à l'intégration du Credential Manager et à des outils de test plus rapides. Comme toujours, vos commentaires sont importants. N'hésitez donc pas à nous faire part de vos commentaires sur ces modifications ou sur ce que vous aimeriez voir ensuite dans notre outil de suivi des problèmes. À vos claviers !

Written by:
Lecture synchronisée