Notícias sobre produtos

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

Leitura de 5 minutos
Meghan Mehta
Mediadora de desenvolvedores, Android

Hoje, a versão de abril de 2026 do Jetpack Compose está estável. Essa 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 nos desse 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 introduzindo uma grande atualização na forma como o Compose processa a temporização de testes. Após o período de ativação anunciado no Compose 1.10, as APIs de teste v2 agora são as padrão, e as APIs v1 foram descontinuadas. A principal mudança é uma mudança no agente 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 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 o conjunto de testes significativamente mais robusto e menos instável.

Para garantir que os testes estejam alinhados com o comportamento padrão da corrotina e evitar problemas de compatibilidade futuros, recomendamos migrar o conjunto de testes. Confira nosso guia de migração abrangente para mapeamentos de API e correções comuns.

Melhorias de elementos compartilhados e ferramentas de animação

Também adicionamos algumas ferramentas úteis de depuração visual 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 quantos matches são encontrados, o que facilita muito a identificação do motivo pelo qual 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 de trackpad

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

Também adicionamos suporte a gestos de trackpad mais complicados reconhecidos pela plataforma desde a API 34, incluindo deslizamentos de dois dedosgestos 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 componentes integrados, com a remoção de folga de toque redundante, um gesto de início de arrastar e soltar mais intuitivo, seleção de clique duplo e triplo em campos de texto e menus de contexto no estilo de computador 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 tipos de entrada, incluindo telas sensíveis ao toque, mouses, trackpads e canetas, e garanta o suporte a rodas de rolagem do mouse e gestos de trackpad.

beforeAndAfter.webp

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

Introduzimos HostDefaultProviderLocalHostDefaultProviderHostDefaultKeyViewTreeHostDefaultKey para fornecer serviços no nível do host diretamente pelo ambiente de execução do Compose. Isso remove a necessidade de 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.

Wrappers de visualização

Visualizações personalizadas do Android Studio é 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, você pode injetar facilmente uma 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

  • Conforme anunciado na postagem do blog do Compose 1.10, estamos descontinuando Modifier.onFirstVisible(). O nome dele geralmente 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 caso de uso.
  • A flag ComposeFoundationFlags.isTextFieldDpadNavigationEnabled foi removida porque a navegação com botão direcional para TextFields agora está sempre ativada por padrão. O novo comportamento garante que os eventos do botão direcional de um gamepad ou controle remoto da TV primeiro movam o cursor na direção especificada. O foco só pode ser movido para outro elemento quando o cursor atinge o final 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 manter-se atualizado com as versões mais recentes, já que o Compose tem como objetivo adotar rapidamente novos compileSdks para fornecer 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 APIs a seguir são introduzidas como @Experimental, e esperamos receber seu feedback ao explorá-las nos apps. Note que @Experimental APIs são fornecidas para avaliação e feedback iniciais e podem passar por mudanças significativas ou remoção em versões futuras.

Estilos (experimental)

Estamos introduzindo uma nova API de base experimental para estilização. A API Style é um novo paradigma para personalizar elementos visuais de componentes, que tradicionalmente era realizado com modificadores. Ela foi projetada para desbloquear uma personalização mais profunda e fácil, expondo um conjunto padrão de propriedades estilizadas com estilo simples baseado 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 estiver estável.

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 registre bugs aqui.

MediaQuery (experimental)

A nova API mediaQuery oferece uma maneira declarativa e eficiente de adaptar a interface ao ambiente. Ela abstrai a recuperação de informações complexas em condições simples em 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, você pode criar experiências altamente responsivas. A performance é integrada ao derivedMediaQuery para processar atualizações de alta frequência, enquanto a capacidade de substituir escopos torna os testes e as visualizações perfeitos em configurações de hardware. Anteriormente, para acessar determinadas propriedades do dispositivo, como se um dispositivo estava no modo de mesa , era necessário escrever muito código boilerplate para fazer isso: 

@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 UIMediaQuery, você pode adicionar a sintaxe mediaQuery para consultar propriedades do dispositivo, como se um dispositivo 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 registre bugs aqui.

Grade (experimental)

Grid é uma nova API poderosa 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. Grid permite definir o layout usando faixas, lacunas e células, oferecendo opções de dimensionamento familiares, 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 colocar itens automaticamente ou abranger explicitamente várias linhas e colunas para 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 o 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 registre bugs aqui

FlexBox (experimental)

FlexBox é um contêiner de layout projetado para interfaces adaptáveis de alta performance. Ele gerencia o dimensionamento de itens e a distribuição de espaço com base nas dimensões do contêiner disponíveis.Ele processa tarefas complexas, como quebra de linha (wrap) e alinhamento de itens em vários eixos (justifyContent, alignItems, alignContent). Ele permite que os itens cresçam (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 registre bugs aqui.

Nova implementação do SlotTable (experimental)

Introduzimos uma nova implementação do SlotTable, que está desativada por padrão nesta versão. SlotTable é a estrutura de dados interna que o ambiente 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 no ambiente de execução. Essa nova implementação foi projetada para melhorar a performance, principalmente em edições aleatórias.

Para testar o novo SlotTable, ative ComposeRuntimeFlags.isLinkBufferComposerEnabled

Comece a programar hoje!

Com tantas novas APIs interessantes no Jetpack Compose e muitas outras chegando, nunca foi um momento melhor para migrar para o Jetpack Compose.Como sempre, valorizamos seu feedback e solicitações de recursos (especialmente em recursos @Experimental que ainda estão em desenvolvimento). Registre-os aqui. Divirta-se!

Escrito por:

Continuar lendo