Notizie sui prodotti

Novità della release di agosto 2026 di Jetpack Compose

Lettura di 5 minuti
Visualizza il profilo di Nick Butcher
Nick Butcher Product Manager

Oggi, la release di agosto 2026 di Jetpack Compose è stabile. Questa release introduce la versione 1.12 nei moduli principali di Compose (vedi il mapping della distinta base), introducendo API visive avanzate come le sfumature mesh e il supporto della gamma cromatica estesa (WCG), funzionalità di layout strutturale come le aree denominate in Grid, integrazione perfetta con Gestore delle credenziali di Android e miglioramenti significativi di test e prestazioni.

Per aggiornare il tuo progetto alla release di oggi, esegui l'upgrade della versione della distinta base di Compose alla versione 2026.08.00:

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

Modifiche che provocano errori

  • AGP e SDK di compilazione: Compose 1.12 aggiorna compileSdk all'API 37, richiedendo AGP 9.1.2 come minimo. Ti ricordiamo che Compose ha sempre come target l'ultima versione di compileSdk. Scopri di più su questa modifica qui.
  • Modifier.onFirstVisible() è deprecato: esegui la migrazione a Modifier.onVisibilityChanged(), che fornisce un monitoraggio più preciso della soglia di visibilità.

Grafica

Sfumature mesh

Compose 1.12 introduce MeshGradientPainter per aiutarti a creare sfumature di colore organiche e multipunto.

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)
)

Per ulteriori informazioni ed esempi, consulta la documentazione.

Supporto di Wide Color Gamut e HDR

I display moderni offrono una fedeltà del colore estesa e una gamma dinamica più elevata. In Compose 1.12 è stato attivato il supporto completo della pipeline per la gamma cromatica estesa (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 conservati fino al rendering della piattaforma senza bloccaggio del colore. 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 a GraphicsLayer e Modifier.graphicsLayer, che puoi utilizzare per aumentare i limiti visivi del livello oltre le dimensioni misurate. Applica LayerOutsets per evitare il comportamento implicito clipToBounds quando il livello viene promosso a un buffer off-screen.

Stili

In occasione di Google I/O, abbiamo condiviso la nostra prima visione dell'API Styles di Compose, un modo unificato e performante per applicare stili 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 di implementare correttamente questo livello di base, l'API rimarrà sperimentale e potresti riscontrare modifiche che causano interruzioni. 

Ottimizzazioni di runtime

Keyed SideEffect Overload

SideEffect ora supporta gli argomenti chiave, che ti consentono di attivare effetti collaterali una tantum ogni volta che cambiano chiavi specifiche. Ciò può portare a un rendimento migliore rispetto all'utilizzo di un LaunchedEffect o DisposableEffect quando non hai bisogno della coroutine o del blocco dispose. SideEffect è fino al 90% più veloce di LaunchedEffect e circa il 20% più veloce di DisposableEffect. Tieni presente che SideEffect ha 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 iniziare dopo il completamento del frame corrente. 

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

Animazione

Transizioni interattive in due fasi

  • Nuovi composable: DeferredAnimatedContent e DeferredAnimatedVisibility consentono di creare transizioni in due fasi piacevoli, ad esempio 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) ora possono essere manipolate manualmente in tempo reale (ad es. tracciando 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 degli elementi condivisi: un nuovo flag permitTransformDuringDeferredTransition in SharedContentConfig controlla 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 sui gesti viene trasferita a un'animazione attivata:

colorCards.gif

Integrazioni di testo, input e piattaforme

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 di caratteri e 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 anche dopo 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 API SelectionState fornisce controllo e osservabilità programmatici sulla selezione del testo all'interno di un SelectionContainer. L'innalzamento di un oggetto SelectionState tramite rememberSelectionState() e il passaggio a SelectionContainer espone selectedTexts come 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 nei 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 composizione ora si integrano in modo nativo con Credential Manager di Android (API 34+) tramite il framework di compilazione automatica (le versioni precedenti all'API 34 sono gestite da androidx.credentials library). Se si allega 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 delle impostazioni di variazione dei caratteri nei caratteri scaricabili.
  • È stato attivato lo scorrimento automatico quando si trascina la selezione di testo oltre la finestra in SelectionContainer.
  • È stato aggiunto il supporto per i suoni di interazione automatici (clic e navigazione con messa a fuoco) ai componenti Compose, con un nuovo composable SoundEffectOnInteraction per consentire l'opt-out. Tieni presente che, in seguito a questa modifica, i listener di clic semantici devono ora essere chiamati dal thread principale, il che potrebbe influire su un numero ridotto di scenari di test.
  • KeyboardType ora include Date, Time, DateTime e SignedDecimal.
  • BasicSecureTextField ora utilizza TextObfuscationMode.System per impostazione predefinita, mentre RevealLastTyped funge da override assoluto.

Miglioramenti del layout

Aree denominate nel layout a griglia

Creare layout 2D complessi è ora più facile con le aree denominate nel componente @Experimental Griglia. Anziché gestire gli indici numerici di colonne e righe tra gli elementi, puoi definire regioni semantiche nel tuo GridConfigurationScope e posizionare i componenti componibili 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 saperne di più, 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 osserviamo un tempo al primo display (il tempo necessario a un'app per produrre il primo frame) paragonabile a Views nei nostri benchmark.

timetoinitialdisplay@2x _v2.png

Aggiornamenti di test e strumenti

Test di sincronizzazione

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 lavoro in sospeso senza far avanzare l'orologio, il che è ideale per i loop di animazione manuali.
  • runWithoutImplicitWait: disattiva temporaneamente la sincronizzazione implicita durante l'avanzamento dei fotogrammi 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 captureToImage ora ti consente di acquisire un popup o una finestra di dialogo insieme al relativo ancoraggio in una singola bitmap.
  • È stato aggiunto onRootWithViewInteraction per limitare le ricerche semantiche di Compose a visualizzazioni Android specifiche. Ciò semplifica il test delle UI ibride, come RecyclerViews, senza richiedere tag di test univoci nel codice di produzione.
  • Ora le annotazioni @PreviewWrapper possono essere applicate alle classi @MultiPreview personalizzate, consentendo configurazioni di anteprima riutilizzabili (come i temi personalizzati) in più componenti.

Buona composizione!

Compose 1.12 rende lo sviluppo di app più semplice ed espressivo che mai, con sfumature mesh, supporto della gamma cromatica ampia, caratteri variabili scaricabili, integrazione di Gestore delle credenziali e strumenti di test più veloci. Come sempre, il tuo contributo è prezioso, quindi condividi il tuo feedback su queste modifiche o su cosa vorresti vedere in futuro nel nostro strumento di monitoraggio dei problemi. Buona composizione!

Continua a leggere