Novedades sobre productos

Novedades de la versión de abril de 2026 de Jetpack Compose

Lectura de 5 min
Meghan Mehta
Developer Advocate, Android

Hoy, la versión de abril de 2026 de Jetpack Compose es estable. Esta versión contiene la versión 1.11 de los módulos principales de Compose (consulta la asignación completa del BOM), herramientas de depuración de elementos compartidos, eventos de trackpad y mucho más. También tenemos algunas APIs experimentales que nos encantaría que probaras y nos enviaras tus comentarios.

Para usar la versión de hoy, actualiza la versión de tu BOM de Compose a la siguiente:

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

Cambios en Compose 1.11.0

Ejecución de corrutinas en pruebas

Presentamos una actualización importante sobre cómo Compose controla el tiempo de las pruebas. Después del período de habilitación anunciado en Compose 1.10, las APIs de prueba de la versión 2 ahora son las predeterminadas y las APIs de la versión 1 quedaron obsoletas. El cambio clave es un cambio en el despachador de pruebas predeterminado. Si bien las APIs de la versión 1 se basaban en UnconfinedTestDispatcher, que ejecutaba corrutinas de inmediato, las APIs de la versión 2 usan StandardTestDispatcher. Esto significa que, cuando se inicia una corrutina en tus pruebas, ahora se pone en cola y no se ejecuta hasta que se avanza el reloj virtual.

Esto simula mejor las condiciones de producción, lo que elimina de manera eficaz las condiciones de carrera y hace que tu paquete de pruebas sea mucho más sólido y menos inestable.

Para asegurarte de que tus pruebas se alineen con el comportamiento estándar de las corrutinas y evitar problemas de compatibilidad en el futuro, te recomendamos que migres tu paquete de pruebas. Consulta nuestra guía de migración integral para obtener información sobre las asignaciones de la API y las correcciones comunes.

Mejoras en los elementos compartidos y herramientas de animación

También agregamos algunas herramientas visuales de depuración útiles para los elementos compartidos y Modifier.animatedBounds. Ahora puedes ver exactamente lo que sucede en segundo plano, como los límites de destino, las trayectorias de animación y la cantidad de coincidencias que se encuentran, lo que facilita mucho detectar por qué una transición podría no comportarse como se espera. Para usar las nuevas herramientas, simplemente rodea tu SharedTransitionLayout con el elemento LookaheadAnimationVisualDebugging componible. 

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

Eventos del panel táctil

Renovamos la compatibilidad con Compose para trackpads, como los trackpads integrados en laptops, los trackpads que se pueden conectar a tablets o los trackpads externos o virtuales. En general, los eventos básicos del panel táctil ahora se considerarán eventos PointerType.Mouse, lo que alinea el comportamiento del mouse y el panel táctil para que coincida mejor con las expectativas del usuario. Anteriormente, estos eventos del panel táctil se interpretaban como dedos táctiles falsos de PointerType.Touch, lo que generaba experiencias del usuario confusas. Por ejemplo, si haces clic y arrastras con un panel táctil, se desplazará en lugar de seleccionar. Al cambiar el tipo de puntero que tienen estos eventos en la versión más reciente de Compose, hacer clic y arrastrar con un trackpad ya no desplazará la pantalla.

También agregamos compatibilidad con gestos de trackpad más complicados que la plataforma reconoce desde la API 34, incluidos los deslizamientos con dos dedos y los pellizcos. Los componentes como Modifier.scrollableModifier.transformable reconocen automáticamente estos gestos para tener un mejor comportamiento con los trackpads.

Estos cambios mejoran el comportamiento de los trackpads en todos los componentes integrados, ya que se quitó la holgura táctil redundante, se agregó un gesto de inicio de arrastrar y soltar más intuitivo, se mejoró la selección con doble clic y triple clic en los campos de texto, y se agregaron menús contextuales con estilo de escritorio en los campos de texto.

Para probar el comportamiento del trackpad, hay nuevas APIs de prueba con performTrackpadInput, que permiten validar el comportamiento de tus apps cuando se usan con un trackpad. Si tienes detectores de gestos personalizados, valida el comportamiento en todos los tipos de entrada, como pantallas táctiles, mouses, paneles táctiles y lápices ópticos, y asegúrate de que se admitan las ruedas de desplazamiento del mouse y los gestos del panel táctil.

beforeAndAfter.webp

Valores predeterminados del host de composición (tiempo de ejecución de Compose)

Presentamos HostDefaultProviderLocalHostDefaultProviderHostDefaultKeyViewTreeHostDefaultKey para proporcionar servicios a nivel del host directamente a través de compose-runtime. Esto elimina la necesidad de que las bibliotecas dependan de compose-ui para las búsquedas, lo que mejora la compatibilidad con Kotlin Multiplatform. Para vincular estos valores al árbol de composición, los autores de la biblioteca pueden usar compositionLocalWithHostDefaultOf para crear un CompositionLocal que resuelva los valores predeterminados del host.

Contenedores de vista previa

Las vistas previas personalizadas de Android Studio son una nueva función que te permite definir exactamente cómo se muestran los contenidos de una vista previa de Compose.

Si implementas la interfaz PreviewWrapperProvider y aplicas la nueva anotación @PreviewWrapper, puedes insertar fácilmente lógica personalizada, como aplicar un Theme específico. La anotación se puede aplicar a una función anotada con @Composable@Preview@MultiPreview, lo que ofrece una solución genérica y fácil de usar que funciona en todas las funciones de vista previa y reduce significativamente el 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")
    }
}

Bajas y eliminaciones

  • Como se anunció en la entrada de blog de Compose 1.10, daremos de baja Modifier.onFirstVisible(). Su nombre a menudo generaba conceptos erróneos, en particular dentro de los diseños diferidos, en los que se activaba varias veces durante el desplazamiento. Te recomendamos que migres a Modifier.onVisibilityChanged(), que permite un seguimiento manual más preciso de los estados de visibilidad adaptados a los requisitos específicos de tu caso de uso.
  • Se quitó la marca ComposeFoundationFlags.isTextFieldDpadNavigationEnabled porque la navegación con el pad direccional para TextFields ahora siempre está habilitada de forma predeterminada. El nuevo comportamiento garantiza que los eventos del pad direccional de un gamepad o un control remoto de TV primero muevan el cursor en la dirección indicada. El enfoque solo se puede mover a otro elemento cuando el cursor llega al final del texto.

Próximas APIs

En el próximo lanzamiento de Compose 1.12.0, compileSdk se actualizará a compileSdk 37, con AGP 9 y todas las apps y bibliotecas que dependen de Compose heredando este requisito. Te recomendamos que te mantengas al día con las versiones más recientes, ya que Compose tiene como objetivo adoptar rápidamente los nuevos compileSdks para proporcionar acceso a las funciones más recientes de Android. Asegúrate de consultar la documentación aquí para obtener más información sobre qué versión de AGP se admite para los diferentes niveles de API. 

En Compose 1.11.0, se introducen las siguientes APIs como @Experimental, y esperamos recibir tus comentarios a medida que las explores en tus apps. Ten en cuenta que @Experimental APIs se proporcionan para la evaluación y los comentarios iniciales, y pueden sufrir cambios significativos o eliminarse en versiones futuras.

Estilos (experimental)

Presentamos una nueva API experimental de base para el diseño. La API de Style es un nuevo paradigma para personalizar los elementos visuales de los componentes, que tradicionalmente se realizaba con modificadores. Está diseñado para desbloquear una personalización más profunda y sencilla, ya que expone un conjunto estándar de propiedades con diseño, con un diseño simple basado en el estado y transiciones animadas. Con esta nueva API, ya estamos viendo prometedores beneficios de rendimiento. Tenemos previsto adoptar los estilos en los componentes de Material una vez que la API de Styles se estabilice.

A continuación, se muestra un ejemplo básico de cómo anular el fondo de un estilo de estado presionado:

@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 documentación y registra los errores aquí.

MediaQuery (experimental)

La nueva API de mediaQuery proporciona una forma declarativa y eficiente de adaptar tu IU a su entorno. Abstrae la recuperación de información compleja en condiciones simples dentro de un UiMediaScope, lo que garantiza que la recomposición solo se produzca cuando sea necesario.

Con la compatibilidad para una amplia variedad de indicadores ambientales, desde capacidades del dispositivo, como tipos de teclado y precisión del puntero, hasta estados contextuales, como el tamaño y la posición de la ventana, puedes crear experiencias profundamente responsivas. El rendimiento está integrado con derivedMediaQuery para controlar las actualizaciones de alta frecuencia, mientras que la capacidad de anular los permisos hace que las pruebas y las vistas previas sean fluidas en todas las configuraciones de hardware. Anteriormente, para acceder a ciertas propiedades del dispositivo, como si un dispositivo estaba en modo de mesa, debías escribir mucho código estándar: 

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

Ahora, con UIMediaQuery, puedes agregar la sintaxis mediaQuery para consultar las propiedades del dispositivo, por ejemplo, si un dispositivo está en modo de mesa:

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

Consulta la documentación y registra los errores aquí.

Cuadrícula (experimental)

Grid es una nueva y potente API para compilar diseños bidimensionales complejos en Jetpack Compose. Si bien RowColumn son excelentes para diseños lineales, Grid te brinda el control estructural necesario para la arquitectura a nivel de la pantalla y los componentes complejos sin la sobrecarga de una lista desplazable. Grid te permite definir tu diseño con pistas, espacios y celdas, y ofrece opciones de tamaño conocidas, como Dp, porcentajes, tamaños de contenido intrínsecos y unidades "Fr" flexibles. 

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

Puedes colocar elementos automáticamente o expandirlos de forma explícita en varias filas y columnas para mayor precisión. Lo mejor de todo es que es muy adaptable: puedes reconfigurar de forma dinámica los tramos y las pistas de la cuadrícula para responder a los estados del dispositivo, como el modo de mesa o los cambios de orientación, lo que garantiza que la IU se vea excelente en todos los factores de forma.

Grid.gif

Consulta la documentación y registra los errores aquí

FlexBox (experimental)

FlexBox es un contenedor de diseño diseñado para IU adaptables y de alto rendimiento. Administra el tamaño de los elementos y la distribución del espacio según las dimensiones disponibles del contenedor. Maneja tareas complejas, como el ajuste (wrap) y la alineación de elementos en varios ejes (justifyContent, alignItems, alignContent). Permite que los elementos crezcan (grow) o se reduzcan (shrink) para llenar el contenedor. 

@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 documentación y registra los errores aquí.

Nueva implementación de SlotTable (experimental)

Implementamos una nueva versión de SlotTable, que está inhabilitada de forma predeterminada en esta versión. SlotTable es la estructura de datos interna que el tiempo de ejecución de Compose usa para hacer un seguimiento del estado de la jerarquía de composición, hacer un seguimiento de las invalidaciones y recomposiciones, almacenar valores recordados y hacer un seguimiento de todos los metadatos de la composición en el tiempo de ejecución. Esta nueva implementación está diseñada para mejorar el rendimiento, principalmente en relación con las ediciones aleatorias.

Para probar la nueva SlotTable, habilita ComposeRuntimeFlags.isLinkBufferComposerEnabled

¡Comienza a programar hoy mismo!

Con tantas APIs nuevas y emocionantes en Jetpack Compose, y muchas más en camino, nunca fue un mejor momento para migrar a Jetpack Compose. Como siempre, valoramos tus comentarios y solicitudes de funciones (en especial, sobre las funciones @Experimental que aún están en desarrollo). Envíanos tus comentarios aquí. ¡Feliz composición!

Escrito por:

Seguir leyendo