Notícias sobre produtos

Novidades da versão de abril de 2026 do Jetpack Compose

Leitura de 5 minutos
Meghan Mehta
Mediador de desenvolvedores, Android

Hoje, a versão de abril de 2026 do Jetpack Compose está estável. Esta versão contém a versão 1.11 dos módulos principais do Compose (consulte o mapeamento completo da BoM), ferramentas de depuração de elementos compartilhados, eventos de trackpad e muito mais. Também temos algumas APIs experimentais que gostaríamos que você testasse e enviasse feedback.

Para usar a versão de hoje, faça upgrade da versão da BOM do Compose para:

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

Mudanças no Compose 1.11.0

Execução de corrotinas em testes

Estamos lançando uma grande atualização na forma como o Compose processa a programação de testes. Após o período de ativação anunciado no Compose 1.10, as APIs de teste v2 agora são o padrão, e as APIs v1 foram descontinuadas. A principal mudança é uma alteração no dispatcher de teste padrão. Enquanto as APIs v1 dependiam do UnconfinedTestDispatcher, que executava corrotinas imediatamente, as APIs v2 usam o StandardTestDispatcher. Isso significa que, quando uma corrotina é iniciada nos seus testes, ela é enfileirada e não é executada até que o relógio virtual seja avançado.

Isso imita melhor as condições de produção, eliminando as condições de corrida e tornando seu pacote de testes muito mais robusto e menos instável.

Para garantir que seus testes estejam alinhados com o comportamento padrão de corrotinas e evitar problemas de compatibilidade no futuro, recomendamos migrar seu pacote de testes. Confira nosso guia de migração abrangente para mapeamentos de API e correções comuns.

Melhorias no elemento compartilhado e ferramentas de animação

Também adicionamos algumas ferramentas visuais úteis de depuração para elementos compartilhados e Modifier.animatedBounds. Agora você pode ver exatamente o que está acontecendo nos bastidores, como limites de destino, trajetórias de animação e quantas correspondências são encontradas. Assim, fica muito mais fácil identificar por que uma transição pode não estar se comportando como esperado. Para usar a nova ferramenta, basta envolver o SharedTransitionLayout com o elemento combinável LookaheadAnimationVisualDebugging

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

Eventos do trackpad

Reformulamos o suporte do Compose para trackpads, como os integrados de laptops, os acopláveis para tablets ou os externos/virtuais. Os eventos básicos do trackpad agora serão considerados eventos PointerType.Mouse, alinhando o comportamento do mouse e do trackpad para corresponder melhor às expectativas do usuário. Antes, esses eventos do trackpad eram interpretados como dedos falsos de tela sensível ao toque de PointerType.Touch, o que levava a experiências confusas para o usuário. Por exemplo, clicar e arrastar com um trackpad rola em vez de selecionar. Ao mudar o tipo de ponteiro desses eventos na versão mais recente do Compose, clicar e arrastar com um trackpad não vai mais rolar.

Também adicionamos suporte a gestos mais complicados do trackpad, reconhecidos pela plataforma desde a API 34, incluindo deslizamentos com dois dedos e gestos de pinça. Esses gestos são reconhecidos automaticamente por componentes como Modifier.scrollable e Modifier.transformable para ter um comportamento melhor com trackpads.

Essas mudanças melhoram o comportamento dos trackpads em todos os componentes integrados, com a remoção da tolerância ao toque redundante, um gesto de arrastar e soltar mais intuitivo, seleção com clique duplo e triplo em campos de texto e menus de contexto no estilo desktop em campos de texto.

Para testar o comportamento do trackpad, há novas APIs de teste com performTrackpadInput,, que permitem validar o comportamento dos apps quando usados com um trackpad. Se você tiver detectores de gestos personalizados, valide o comportamento em todos os tipos de entrada, incluindo telas sensíveis ao toque, mouses, trackpads e stylus. Além disso, verifique se há suporte para rolagem do mouse e gestos do trackpad.

beforeAndAfter.webp

Padrões do host de composição (tempo de execução do Compose)

Introduzimos HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey e ViewTreeHostDefaultKey para fornecer serviços no nível do host diretamente pelo compose-runtime. Isso remove a necessidade de as bibliotecas dependerem de compose-ui para pesquisas, oferecendo melhor suporte ao Kotlin Multiplatform. Para vincular esses valores à árvore de composição, os autores da biblioteca podem usar compositionLocalWithHostDefaultOf para criar um CompositionLocal que resolva os padrões do host.

Visualizar wrappers

As visualizações personalizadas do Android Studio são um novo recurso que permite definir exatamente como o conteúdo de uma visualização do Compose é exibido.

Ao implementar a interface PreviewWrapperProvider e aplicar a nova anotação @PreviewWrapper, é fácil injetar lógica personalizada, como aplicar um Theme específico. A anotação pode ser aplicada a uma função anotada com @Composable e @Preview ou @MultiPreview, oferecendo uma solução genérica e fácil de usar que funciona em recursos de visualização e reduz significativamente o código repetitivo.

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

Descontinuações e remoções

  • Como anunciado na postagem do blog sobre o Compose 1.10, estamos descontinuando o Modifier.onFirstVisible(). O nome dele muitas vezes levava a equívocos, principalmente em layouts lentos, em que ele era acionado várias vezes durante a rolagem. Recomendamos migrar para Modifier.onVisibilityChanged(), que permite um rastreamento manual mais preciso dos estados de visibilidade adaptados aos requisitos específicos do seu caso de uso.
  • A flag ComposeFoundationFlags.isTextFieldDpadNavigationEnabled foi removida porque a navegação com o D-pad para TextFields agora está sempre ativada por padrão. O novo comportamento garante que os eventos do D-pad de um gamepad ou controle remoto de TV primeiro movam o cursor na direção indicada. O foco só pode ser movido para outro elemento quando o cursor chega ao fim do texto.

Próximas APIs

Na próxima versão do Compose 1.12.0, o compileSdk será atualizado para compileSdk 37, com o AGP 9 e todos os apps e bibliotecas que dependem do Compose herdando esse requisito. Recomendamos que você mantenha as versões mais recentes, já que o Compose busca adotar rapidamente novos compileSdks para oferecer acesso aos recursos mais recentes do Android. Confira a documentação aqui para mais informações sobre qual versão do AGP é compatível com diferentes níveis de API. 

No Compose 1.11.0, as seguintes APIs são introduzidas como @Experimental. Aguardamos seu feedback enquanto você as explora nos seus apps. Os @Experimental APIs são fornecidos para avaliação e feedback iniciais e podem passar por mudanças significativas ou remoção em versões futuras.

Estilos (experimental)

Estamos lançando uma nova API experimental de base para estilização. A API Style é um novo paradigma para personalizar elementos visuais de componentes, o que tradicionalmente era feito com modificadores. Ele foi projetado para permitir uma personalização mais profunda e fácil, expondo um conjunto padrão de propriedades estilizadas com estilização simples baseada em estado e transições animadas. Com essa nova API, já estamos vendo benefícios de performance promissores. Planejamos adotar estilos em componentes do Material quando a API Style se estabilizar.

Um exemplo básico de substituição de um plano de fundo de estilo de estado pressionado:

@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

Confira a documentação e informe os bugs aqui.

MediaQuery (experimental)

A nova API mediaQuery oferece uma maneira declarativa e eficiente de adaptar a interface ao ambiente. Ele abstrai a recuperação de informações complexas em condições simples dentro de um UiMediaScope, garantindo que a recomposição só aconteça quando necessário.

Com suporte a uma ampla variedade de indicadores ambientais, desde recursos do dispositivo, como tipos de teclado e precisão do ponteiro, até estados contextuais, como tamanho e posição da janela, é possível criar experiências altamente responsivas. O desempenho é integrado com o derivedMediaQuery para processar atualizações de alta frequência, e a capacidade de substituir escopos facilita os testes e as prévias em várias configurações de hardware. Antes, para acessar determinadas propriedades do dispositivo, como se ele estava no modo de mesa, era necessário escrever muito código padrão: 

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

Agora, com o UIMediaQuery, é possível adicionar a sintaxe mediaQuery para consultar propriedades do dispositivo, como se ele está no modo de mesa:

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

Confira a documentação e informe os bugs aqui.

Grade (experimental)

O Grid é uma nova API eficiente para criar layouts bidimensionais complexos no Jetpack Compose. Embora Row e Column sejam ótimos para designs lineares, Grid oferece o controle estrutural necessário para arquitetura no nível da tela e componentes complexos sem a sobrecarga de uma lista rolável. Com Grid, é possível definir seu layout usando faixas, lacunas e células, oferecendo opções de dimensionamento conhecidas, como Dp, porcentagens, tamanhos de conteúdo intrínsecos e unidades "Fr" flexíveis. 

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

Você pode posicionar itens automaticamente ou abranger várias linhas e colunas para ter mais precisão. O melhor de tudo é que ele é altamente adaptável. Você pode reconfigurar dinamicamente as faixas e os intervalos da grade para responder a estados do dispositivo, como modo de mesa ou mudanças de orientação, garantindo que a interface tenha uma ótima aparência em todos os formatos.

Grid.gif

Confira a documentação e informe os bugs aqui

FlexBox (experimental)

O FlexBox é um contêiner de layout projetado para interfaces adaptáveis de alto desempenho. Ele gerencia o dimensionamento de itens e a distribuição de espaço com base nas dimensões disponíveis do contêiner.  Ele lida com tarefas complexas, como quebra de texto (wrap) e alinhamento de vários eixos de itens (justifyContent, alignItems, alignContent). Ele permite que os itens aumentem (grow) ou diminuam (shrink) para preencher o contêiner. 

@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

Confira a documentação e informe os bugs aqui.

Nova implementação do SlotTable (experimental)

Implementamos uma nova versão do SlotTable, que está desativada por padrão nesta versão. SlotTable é a estrutura de dados interna que o tempo de execução do Compose usa para rastrear o estado da hierarquia de composição, rastrear invalidações/recomposições, armazenar valores lembrados e rastrear todos os metadados da composição durante a execução. Essa nova implementação foi criada para melhorar a performance, principalmente em edições aleatórias.

Para testar o novo SlotTable, ative o ComposeRuntimeFlags.isLinkBufferComposerEnabled

Comece a programar hoje!

Com tantas APIs novas e interessantes no Jetpack Compose, e muitas outras chegando, nunca houve um momento melhor para migrar para o Jetpack Compose.  Como sempre, valorizamos seu feedback e pedidos de recursos (principalmente sobre recursos do @Experimental que ainda estão em desenvolvimento). Envie suas sugestões aqui. Divirta-se!

Escrito por:

Continuar lendo