Oggi, la release di agosto 2026 di Jetpack Compose è stabile. Questa release introduce la versione 1.12 nei moduli principali di Compose (vedi la mappatura completa del BOM), introducendo API visive avanzate come Mesh Gradients e il supporto per la gamma di colori ampia (WCG), funzionalità di layout strutturale come le aree denominate in Grid, l'integrazione perfetta con Credential Manager di Android e miglioramenti significativi in termini di test e prestazioni.
Per aggiornare il tuo progetto alla release di oggi, esegui l'upgrade della versione del BOM di Compose a 2026.08.00:
implementation(platform("androidx.compose:compose-bom:2026.08.00"))
Modifiche che causano interruzioni
- AGP e SDK di compilazione: Compose 1.12 aggiorna compileSdk all'API 37, richiedendo un AGP minimo 9.1.2. Ti ricordiamo che Compose avrà sempre come target l'ultima versione di compileSdk. Scopri di più su questa modifica qui.
Modifier.onFirstVisible()è obsoleta: esegui la migrazione a Modifier.onVisibilityChanged(), che fornisce un monitoraggio più preciso della soglia di visibilità.
Grafica
Mesh Gradients
Compose 1.12 introduce MeshGradientPainter per aiutarti a creare gradienti di colore organici a più punti.
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) )
Per ulteriori informazioni ed esempi, consulta la documentazione.
Supporto per la gamma di colori ampia e l'HDR
I display moderni offrono una fedeltà dei colori estesa e una gamma dinamica più elevata. In Compose 1.12, è stato abilitato il supporto completo della pipeline per la gamma di colori ampia (P3) e il rendering HDR in tutta la grafica, la pittura e gli shader di Compose. I colori definiti in spazi colore non sRGB (come Display P3) vengono mantenuti fino al rendering della piattaforma senza il blocco dei colori. I colori torneranno in modo sicuro a sRGB se utilizzano uno spazio colore non supportato (ad es. CieXyz, CieLab o Oklab), si basano su uno spazio colore in una versione di Android non supportata (ad es. Bt2020Hlg su Android 13 e versioni precedenti) o se l'app è in esecuzione su Android 9 (API 28) e versioni precedenti.
Altre modifiche importanti:
LayerOutsetsè stato aggiunto aGraphicsLayereModifier.graphicsLayer, che puoi utilizzare per aumentare i limiti visivi del livello oltre le dimensioni misurate. ApplicaLayerOutsetsper evitare il comportamentoclipToBoundsimplicito quando il livello viene promosso a un buffer fuori schermo.
Stili
In occasione di Google I/O, abbiamo condiviso la nostra visione iniziale dell'API Styles di Compose, un modo unificato e performante per applicare lo stile ai componenti. Da allora, abbiamo continuato a sviluppare l'architettura sottostante per garantire una rigorosa sicurezza dei tipi e una correttezza prevedibile, nonché per supportare la creazione di sistemi di progettazione personalizzati.
Per assicurarci che questo livello fondamentale sia corretto, l'API rimarrà sperimentale e potresti riscontrare modifiche che causano interruzioni.
Ottimizzazioni di runtime
Sovraccarico SideEffect con chiave
SideEffect ora supporta gli argomenti chiave, che ti consentono di attivare effetti collaterali una tantum ogni volta che cambiano chiavi specifiche. Questo può portare a prestazioni migliori rispetto all'utilizzo di LaunchedEffect o DisposableEffect quando non hai bisogno della coroutine o del blocco di eliminazione. SideEffect è fino al 90% più veloce di LaunchedEffect e circa il 20% più veloce di DisposableEffect. Tieni presente che SideEffect esegue il suo effetto prima di DisposableEffect e LaunchedEffect, quindi fai attenzione se esegui la migrazione degli effetti esistenti a questa API, in particolare per LaunchedEffects che si basano sull'invio per l'avvio dopo il completamento del frame corrente.
@Composable fun AnalyticsTracker(userId: String, screenName: String) { SideEffect(key1 = userId, key2 = screenName) { analytics.logScreenView(userId, screenName) } }
Animazione
DeferredTargetAnimationnon è più in stato sperimentale.
Transizioni interattive a due fasi
- Nuovi composable:
DeferredAnimatedContenteDeferredAnimatedVisibilityconsentono di creare transizioni a due fasi, ad es. per il monitoraggio del gesto Indietro predittivo. - Controllo manuale dell'animazione: durante la fase posticipata di una transizione, le proprietà animate (come la scala o l'offset) possono ora essere manipulate manualmente in tempo reale (ad es. monitorando un gesto di scorrimento).
- Trasferimento senza interruzioni: al termine della fase posticipata, il motore di transizione prende il controllo ed esegue un trasferimento senza interruzioni, incluso il trasferimento della velocità, alla transizione automatica.
- Supporto per gli elementi condivisi: un nuovo flag
permitTransformDuringDeferredTransitioninSharedContentConfigcontrolla se gli elementi condivisi si trasformano visivamente insieme ai relativi contenitori principali durante la fase di transizione posticipata.
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) }
Di seguito sono riportate due demo di casi d'uso in cui un'animazione basata su gesti viene trasferita a un'animazione attivata:
Testo, input e integrazioni della piattaforma
Formattazione del testo modificabile
Le nuove API offrono la formattazione RTF per il testo modificabile in BasicTextField. Ora puoi applicare e manipolare in modo programmatico la formattazione dei caratteri e dei paragrafi in linea utilizzando SpanStyle e ParagraphStyle tramite il nuovo metodo addStyle() all'interno di un ambito TextFieldBuffer (ad esempio all'interno di textFieldState.edit { ... } o di un InputTransformation). Inoltre, TextFieldBuffer fornisce le API getSpanStyles() e getParagraphStyles() che restituiscono oggetti TrackedRange, consentendoti di leggere, aggiornare o rimuovere gli stili applicati. Per completare la creazione della formattazione, TextFieldState ora espone una proprietà textStyles di sola lettura per eseguire query sugli stili attivi negli intervalli, mentre TextFieldBuffer fornisce originalTextStyles per esaminare lo stato della formattazione prima di una modifica. La formattazione del testo e le annotazioni personalizzate vengono mantenute durante le modifiche alla configurazione.
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
Selezione del testo
Una nuova SelectionState API fornisce il controllo programmatico e l'osservabilità della selezione del testo all'interno di un SelectionContainer. L'hosting di un oggetto SelectionState tramite rememberSelectionState() e il passaggio a SelectionContainer espone selectedTexts come un elenco reattivo di AnnotatedStrings e fornisce metodi come selectAll(), clear(), select(TextRange) e extendSelectionByWord().
Inoltre, utilizza getSelectableTexts() per recuperare tutti gli elementi di testo selezionabili in ordine di layout e selezionare il testo tra i composable in SelectionContainer utilizzando un intervallo 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.") } } }
Integrazione di Gestore delle credenziali
I campi di testo di Compose ora si integrano in modo nativo con Credential Manager di Android (API 34 e versioni successive) tramite il framework di compilazione automatica (le versioni precedenti all'API 34 sono gestite da androidx.credentials library). Collegando la nuova proprietà semantica credentialRequest con CredentialRequestData, gli input di testo possono richiedere passkey, credenziali salvate o richieste di accesso direttamente nel flusso di input dell'utente.
@Composable fun LoginField(textFieldState: TextFieldState) { val credentialData = remember { CredentialRequestData( // Specify Credential Manager request options ) } BasicTextField( state = textFieldState, modifier = Modifier.semantics { credentialRequest = credentialData } ) }
Altre modifiche importanti:
- Supporto per le impostazioni delle varianti dei caratteri nei caratteri scaricabili.
- È stato attivato lo scorrimento automatico quando si trascina la selezione del testo oltre la finestra di visualizzazione in
SelectionContainer. - È stato aggiunto il supporto per i suoni di interazione automatica (clic e navigazione con il focus) ai componenti di Compose, con un nuovo
SoundEffectOnInteractioncomposable per consentire l'esclusione esplicita. Tieni presente che, di conseguenza, ora i listener di clic semantici devono essere chiamati dal thread principale, il che potrebbe influire su un piccolo numero di casi di test. KeyboardTypeora includeDate,Time,DateTime, eSignedDecimal.BasicSecureTextFieldora utilizzaTextObfuscationMode.Systemper impostazione predefinita, mentreRevealLastTypedfunge da override assoluto.
Miglioramenti del layout
Aree denominate nel layout a griglia
La creazione di layout 2D complessi è ora più semplice con le aree denominate nel componente @Experimental Grid. Anziché gestire gli indici numerici di colonne e righe tra gli elementi, puoi definire regioni semantiche in GridConfigurationScope e posizionare i composable in base al nome dell'area.
@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")) } }
Per ulteriori informazioni, consulta la documentazione.
Prestazioni
Come per ogni release, continuiamo a investire nelle prestazioni di Compose per garantire che il framework ti aiuti a creare app belle e performanti. In questa release ci siamo concentrati sul miglioramento delle prestazioni di avvio e ora stiamo riscontrando un Time to Initial Display (il tempo necessario a un'app per produrre il primo frame) paragonabile a Views nei nostri benchmark.
Upgrade di test e strumenti
Sincronizzazione dei test
Compose 1.12 introduce nuove API di test progettate per ridurre i tempi di esecuzione dei test ed eliminare l'instabilità durante il campionamento dello stato:
hasPendingWork: controlla passivamente se la UI ha un lavoro in attesa senza avanzare l'orologio, ideale per i loop di animazione manuali.runWithoutImplicitWait: disabilita temporaneamente la sincronizzazione implicita quando si scorrono i frame dell'orologio manuale (ad es. test di animazione).
@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) } } } }
Altre modifiche importanti:
- L'API
captureToImageora ti consente di acquisire un popup o una finestra di dialogo insieme al relativo ancoraggio in una singola bitmap. - È stato aggiunto
onRootWithViewInteractionper limitare le ricerche semantiche di Compose a View Android specifiche. Questo semplifica il test delle UI ibride, comeRecyclerViews, senza richiedere tag di test univoci nel codice di produzione. @PreviewWrapperannotazioni ora possono essere applicate alle classi@MultiPreviewpersonalizzate, consentendo configurazioni di anteprima riutilizzabili (come i temi personalizzati) in più componenti.
Buona composizione
Compose 1.12 semplifica e rende più espressivo che mai lo sviluppo di app, con gradienti mesh, supporto per la gamma di colori ampia, caratteri variabili scaricabili, integrazione di Gestore delle credenziali e strumenti di test più veloci. Come sempre, apprezziamo il tuo contributo, quindi condividi il tuo feedback su queste modifiche o su ciò che ti piacerebbe vedere in futuro nel nostro strumento di monitoraggio dei problemi. Buona composizione!
-
Novità sul prodottoCon l'introduzione di Pixel 11 Pro Fold, Pixel Watch 5 e dell'intera famiglia Pixel, gli utenti passano senza problemi tra diverse dimensioni dello schermo, posture uniche ed esperienze intelligenti.
-
Novità sul prodottoOggi festeggiamo ufficialmente i cinque anni dalla release di Jetpack Compose 1.0. Dalla versione 1.0, annunciata il 28 luglio 2021, alla nostra ultima release 1.11, abbiamo assistito a una significativa evoluzione delle API nel corso degli anni e ci prendiamo un momento per festeggiare.
Rebecca Franks, Nick Butcher, Loryn Hairston • Lettura di 4 minuti -
Novità sul prodottoNei quasi 5 anni dal lancio di Jetpack Compose, abbiamo investito per offrirti tutte le funzionalità, le prestazioni e gli strumenti di cui hai bisogno per creare UI straordinarie su una varietà di dispositivi Android.
Nick Butcher • Lettura di 2 minuti
Ricevi ogni settimana nella tua casella di posta gli ultimi approfondimenti sullo sviluppo Android