Novità sul prodotto

Novità della release di Jetpack Compose di aprile 2026

Lettura di 5 minuti
Meghan Mehta
Consulente per gli sviluppatori, Android

Oggi, la release di aprile 2026 di Jetpack Compose è stabile. Questa release contiene la versione 1.11 dei moduli principali di Compose (vedi il mapping della BOM completo), strumenti di debug degli elementi condivisi, eventi del trackpad e altro ancora. Abbiamo anche alcune API sperimentali che ci piacerebbe che provassi e su cui ci fornissi un feedback.

Per utilizzare la release di oggi, esegui l'upgrade della versione di Compose BOM a:

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

Modifiche in Compose 1.11.0

Esecuzione di coroutine nei test

Stiamo introducendo un importante aggiornamento al modo in cui Compose gestisce la tempistica dei test. Dopo il periodo di attivazione annunciato in Compose 1.10, le API di test v2 sono ora le API predefinite e le API v1 sono state ritirate. La modifica principale è il cambiamento del dispatcher di test predefinito. Mentre le API v1 si basavano su UnconfinedTestDispatcher, che eseguiva immediatamente le coroutine, le API v2 utilizzano StandardTestDispatcher. Ciò significa che quando una coroutine viene avviata nei test, viene messa in coda e non viene eseguita finché l'orologio virtuale non viene avanzato.

In questo modo vengono simulate meglio le condizioni di produzione, eliminando efficacemente le condizioni di competizione e rendendo la suite di test molto più solida e meno instabile.

Per assicurarti che i test siano in linea con il comportamento standard delle coroutine ed evitare problemi di compatibilità futuri, ti consigliamo vivamente di eseguire la migrazione della suite di test. Consulta la nostra guida alla migrazione completa per le mappature delle API e le correzioni comuni.

Miglioramenti degli elementi condivisi e strumenti di animazione

Abbiamo anche aggiunto alcuni utili strumenti di debug visivo per gli elementi condivisi e Modifier.animatedBounds. Ora puoi vedere esattamente cosa succede sotto il cofano, ad esempio i limiti del target, le traiettorie dell'animazione e quanti match vengono trovati, il che rende molto più facile capire perché una transizione potrebbe non comportarsi come previsto. Per utilizzare il nuovo strumento, racchiudi semplicemente il tuo SharedTransitionLayout con il composable LookaheadAnimationVisualDebugging

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

Eventi del trackpad

Abbiamo rinnovato il supporto di Scrivi per i trackpad, come i trackpad integrati dei laptop, i trackpad collegabili per i tablet o i trackpad esterni/virtuali. Gli eventi di base del trackpad ora verranno generalmente considerati eventi PointerType.Mouse, allineando il comportamento del mouse e del trackpad in modo da soddisfare meglio le aspettative degli utenti. In precedenza, questi eventi del trackpad venivano interpretati come dita finte del touchscreen di PointerType.Touch, il che portava a esperienze utente confuse. Ad esempio, fare clic e trascinare con un trackpad scorre anziché selezionare. Se modifichi il tipo di puntatore di questi eventi nell'ultima release di Compose, fare clic e trascinare con un trackpad non scorrerà più.

Abbiamo anche aggiunto il supporto per i gesti del trackpad più complessi riconosciuti dalla piattaforma a partire dall'API 34, tra cui scorrimenti con due dita e pizzichi. Questi gesti vengono riconosciuti automaticamente da componenti come Modifier.scrollableModifier.transformable per un comportamento migliore con i trackpad.

Queste modifiche migliorano il comportamento dei trackpad nei componenti integrati, con la rimozione del margine di errore ridondante, un gesto di trascinamento più intuitivo, la selezione con doppio clic e triplo clic nei campi di testo e i menu contestuali in stile desktop nei campi di testo.

Per testare il comportamento del trackpad, sono disponibili nuove API di test con performTrackpadInput, che consentono di convalidare il comportamento delle tue app quando vengono utilizzate con un trackpad. Se hai rilevatori di gesti personalizzati, convalida il comportamento tra i tipi di input, inclusi touchscreen, mouse, trackpad e stili, e assicurati che siano supportate le rotelline del mouse e i gesti del trackpad.

beforeAndAfter.webp

Impostazioni predefinite dell'host di composizione (runtime di Compose)

Abbiamo introdotto HostDefaultProviderLocalHostDefaultProviderHostDefaultKeyViewTreeHostDefaultKey per fornire servizi a livello di host direttamente tramite compose-runtime. In questo modo, le librerie non devono più dipendere da compose-ui per le ricerche, supportando meglio Kotlin Multiplatform. Per collegare questi valori all'albero di composizione, gli autori della libreria possono utilizzare compositionLocalWithHostDefaultOf per creare un CompositionLocal che risolva i valori predefiniti dell'host.

Visualizzare l'anteprima dei wrapper

Anteprime personalizzate di Android Studio è una nuova funzionalità che ti consente di definire esattamente come vengono visualizzati i contenuti di un'anteprima di Compose.

Implementando l'interfaccia PreviewWrapperProvider e applicando la nuova annotazione @PreviewWrapper, puoi inserire facilmente una logica personalizzata, ad esempio applicare un Theme specifico. L'annotazione può essere applicata a una funzione annotata con @Composable@Preview@MultiPreview, offrendo una soluzione generica e facile da usare che funziona con le funzionalità di anteprima e riduce significativamente il codice ripetitivo.

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

Ritiri e rimozioni

  • Come annunciato nel post del blog relativo a Compose 1.10, stiamo ritirando Modifier.onFirstVisible(). Il suo nome spesso portava a idee sbagliate, in particolare nei layout pigri, dove veniva attivato più volte durante lo scorrimento. Ti consigliamo di eseguire la migrazione a Modifier.onVisibilityChanged(), che consente un monitoraggio manuale più preciso degli stati di visibilità in base ai requisiti specifici del tuo caso d'uso.
  • Il flag ComposeFoundationFlags.isTextFieldDpadNavigationEnabled è stato rimosso perché la navigazione D-pad per TextFields ora è sempre attiva per impostazione predefinita. Il nuovo comportamento garantisce che gli eventi del D-pad di un gamepad o di un telecomando TV spostino prima il cursore nella direzione specificata. Lo stato attivo può spostarsi su un altro elemento solo quando il cursore raggiunge la fine del testo.

API in arrivo

Nella prossima release di Compose 1.12.0, compileSdk verrà aggiornato a compileSdk 37, con AGP 9 e tutte le app e le librerie che dipendono da Compose che ereditano questo requisito. Ti consigliamo di rimanere al passo con le ultime versioni rilasciate, in quanto Compose mira ad adottare tempestivamente le nuove compileSdks per fornire l'accesso alle funzionalità Android più recenti. Per ulteriori informazioni su quale versione di AGP è supportata per i diversi livelli API, consulta la documentazione qui

In Compose 1.11.0, le seguenti API vengono introdotte come @Experimental e non vediamo l'ora di ricevere il tuo feedback mentre le esplori nelle tue app. Tieni presente che @Experimental APIs vengono forniti per la valutazione e il feedback iniziali e potrebbero subire modifiche significative o essere rimossi nelle versioni future.

Stili (sperimentale)

Stiamo introducendo una nuova API di base sperimentale per lo styling. L'API Style è un nuovo paradigma per la personalizzazione degli elementi visivi dei componenti, che tradizionalmente veniva eseguita con i modificatori. È progettato per consentire una personalizzazione più profonda e semplice, esponendo un insieme standard di proprietà modificabili con stili semplici basati sullo stato e transizioni animate. Con questa nuova API, stiamo già riscontrando promettenti vantaggi in termini di prestazioni. Prevediamo di adottare gli stili nei componenti Material una volta che l'API Style sarà stabile.

Un esempio di base di override dello sfondo di uno stile di stato premuto:

@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

Consulta la documentazione e segnala eventuali bug qui.

MediaQuery (sperimentale)

La nuova API mediaQuery offre un modo dichiarativo e performante per adattare la UI al suo ambiente. Estrae il recupero di informazioni complesse in condizioni semplici all'interno di un UiMediaScope, garantendo che la ricomposizione avvenga solo quando necessario.

Grazie al supporto di un'ampia gamma di segnali ambientali, dalle funzionalità del dispositivo come i tipi di tastiera e la precisione del puntatore agli stati contestuali come le dimensioni e la postura della finestra, puoi creare esperienze altamente reattive. Le prestazioni sono integrate con derivedMediaQuery per gestire gli aggiornamenti ad alta frequenza, mentre la possibilità di ignorare gli ambiti rende i test e le anteprime fluidi in tutte le configurazioni hardware. In precedenza, per accedere a determinate proprietà del dispositivo, ad esempio se un dispositivo era in modalità Tavolo, era necessario scrivere molto boilerplate: 

@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()
    }
}

Ora, con UIMediaQuery, puoi aggiungere la sintassi mediaQuery per eseguire query sulle proprietà del dispositivo, ad esempio se un dispositivo è in modalità Tabletop:

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

Consulta la documentazione e segnala eventuali bug qui.

Griglia (sperimentale)

Grid è una nuova e potente API per la creazione di layout bidimensionali complessi in Jetpack Compose. Row e Column sono ideali per i design lineari, mentre Grid ti offre il controllo strutturale necessario per l'architettura a livello di schermata e per i componenti complessi senza l'overhead di un elenco scorrevole. Grid ti consente di definire il layout utilizzando tracce, spazi e celle, offrendo opzioni di dimensionamento familiari come Dp, percentuali, dimensioni intrinseche dei contenuti e unità "Fr" flessibili. 

@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()
    }
}

Puoi posizionare gli elementi automaticamente o distribuirli in modo esplicito su più righe e colonne per una maggiore precisione. La cosa migliore è che è altamente adattabile: puoi riconfigurare dinamicamente le tracce e le estensioni della griglia per rispondere agli stati del dispositivo, come la modalità Tabletop o le modifiche all'orientamento, assicurandoti che la UI abbia un bell'aspetto su tutti i fattori di forma.

Grid.gif

Consulta la documentazione e segnala eventuali bug qui

FlexBox (sperimentale)

FlexBox è un contenitore di layout progettato per interfacce utente adattive e ad alte prestazioni. Gestisce il dimensionamento degli articoli e la distribuzione dello spazio in base alle dimensioni del contenitore disponibili. Gestisce attività complesse come il wrapping (wrap) e l'allineamento multiasse degli elementi (justifyContent, alignItems, alignContent). Consente agli elementi di crescere (grow) o ridursi (shrink) per riempire il contenitore. 

@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

Consulta la documentazione e segnala eventuali bug qui.

Nuova implementazione di SlotTable (sperimentale)

Abbiamo introdotto una nuova implementazione di SlotTable, che è disattivata per impostazione predefinita in questa release. SlotTable è la struttura di dati interna utilizzata dal runtime di Compose per monitorare lo stato della gerarchia di composizione, tenere traccia delle invalidazioni/ricomposizioni, archiviare i valori memorizzati e monitorare tutti i metadati della composizione in fase di runtime. Questa nuova implementazione è progettata per migliorare il rendimento, principalmente in relazione alle modifiche casuali.

Per provare il nuovo SlotTable, attiva ComposeRuntimeFlags.isLinkBufferComposerEnabled

Inizia a programmare oggi stesso.

Con così tante nuove API entusiasmanti in Jetpack Compose e molte altre in arrivo, non c'è mai stato momento migliore per eseguire la migrazione a Jetpack Compose. Come sempre, apprezziamo il tuo feedback e le tue richieste di funzionalità (soprattutto quelle relative alle funzionalità di @Experimental ancora in fase di sviluppo). Inviacele qui. Buona composizione!

Scritto da:

Continua a leggere