Novedades de productos

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

Lectura de 6 min
Ver el perfil de Meghan Mehta
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 de la BOM), herramientas de depuración de elementos compartidos, eventos de panel táctil y mucho más. También tenemos algunas APIs experimentales que nos gustaría que pruebes y nos envíes tus comentarios.

Para usar la versión de hoy, actualiza la versión de la 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 los tiempos 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 dejaron de estar disponibles. El cambio clave es un cambio en el despachador de pruebas predeterminado. Mientras que las APIs de la versión 1 dependían de 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 adelanta el reloj virtual.

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

Para garantizar 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 completa guía de migración para conocer las asignaciones de APIs y las correcciones habituales.

Mejoras en los elementos compartidos y herramientas de animación

También agregamos algunas herramientas visuales útiles de depuración para 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 cuántas coincidencias 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 de componibilidad LookaheadAnimationVisualDebugging. 

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 de Compose con los paneles táctiles, como los integrados en laptops, los que se conectan a tablets o los externos o virtuales. Ahora, los eventos básicos del panel táctil se considerarán, en general, eventos PointerType.Mouse, lo que alineará el comportamiento del mouse y del panel táctil para que se adapte mejor a las expectativas de los usuarios. Anteriormente, estos eventos del panel táctil se interpretaban como dedos de pantalla táctil falsos de PointerType.Touch, lo que generaba experiencias del usuario confusas. Por ejemplo, si hacías clic y arrastrabas con un panel táctil, se desplazaba en lugar de seleccionar. Si cambias el tipo de puntero que tienen estos eventos en la versión más reciente de Compose, hacer clic y arrastrar con un panel táctil ya no desplazará la pantalla.

También agregamos compatibilidad con gestos más complicados del panel táctil, como los reconoce la plataforma desde la API 34, incluidos deslizamientos con dos dedos y pellizcos. Los componentes como Modifier.scrollable y Modifier.transformable reconocen automáticamente estos gestos para tener un mejor comportamiento con los paneles táctiles.

Estos cambios mejoran el comportamiento de los paneles táctiles en los componentes integrados, ya que se quitó el margen de arrastre redundante, se agregó un gesto de inicio de arrastrar y soltar más intuitivo, se agregó la selección con doble 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 panel táctil, hay nuevas APIs de prueba con performTrackpadInput, que permiten validar el comportamiento de tus apps cuando se usan con un panel táctil. Si tienes detectores de gestos personalizados, valida el comportamiento en todos los tipos de entrada, incluidas las pantallas táctiles, los mouses, los paneles táctiles y las plumas stylus, y asegúrate de que se admitan las ruedas del mouse y los gestos del panel táctil.

beforeAndAfter.webp

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

Presentamos HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey y ViewTreeHostDefaultKey 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 bibliotecas 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 muestra el contenido 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 y @Preview o @MultiPreview, lo que ofrece una solución genérica y fácil de usar que funciona en todas las funciones de versión preliminar y reduce significativamente el código repetitivo.

class ThemeWrapper: PreviewWrapperProvider {
    @Composable
    override fun Wrap(content: @Composable (() -> Unit)) {
        JetsnackTheme {
            content()
        }
    }
}


@PreviewWrapper(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 solía generar confusiones, en especial en 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 pad direccional para TextFields ahora siempre está habilitada de forma predeterminada. El nuevo comportamiento garantiza que los eventos del pad direccional de un control de juegos o un control remoto de TV muevan primero 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 la próxima versión de Compose 1.12.0, el compileSdk se actualizará a compileSdk 37, con AGP 9, y todas las apps y bibliotecas que dependan de Compose heredarán este requisito. Te recomendamos que te mantengas al tanto de las versiones más recientes, ya que Compose tiene como objetivo adoptar con rapidez las nuevas 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 del AGP es compatible con los diferentes niveles de API. 

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

Estilos (experimental)

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

Este es un ejemplo básico de cómo anular un fondo de 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 envía los errores aquí.

MediaQuery (experimental)

La nueva API de mediaQuery proporciona una forma declarativa y de alto rendimiento para 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 ocurra cuando sea necesario.

Gracias a la compatibilidad con una amplia variedad de indicadores del entorno, desde las capacidades del dispositivo, como los tipos de teclado y la precisión del puntero, hasta los estados contextuales, como el tamaño de la ventana y la posición, puedes crear experiencias altamente responsivas. El rendimiento se integra 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 obtener acceso a ciertas propiedades del dispositivo, como si un dispositivo estaba en modo mesa, debías escribir mucho código estándar para hacerlo: 

@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 está en modo mesa:

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

Consulta la documentación y envía los errores aquí.

Cuadrícula (experimental)

Grid es una nueva API potente para crear diseños bidimensionales complejos en Jetpack Compose. Si bien Row y Column 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 distribuirlos de forma explícita en varias filas y columnas para lograr precisión. Lo mejor de todo es que es muy adaptable: puedes reconfigurar de forma dinámica las pistas y los intervalos 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 tu IU se vea genial en todos los factores de forma.

Grid.gif

Consulta la documentación y envía los errores aquí. 

FlexBox (experimental)

FlexBox es un contenedor de diseño diseñado para IU adaptables de alto rendimiento. Administra el tamaño de los elementos y la distribución del espacio según las dimensiones disponibles del contenedor.  Controla tareas complejas, como el ajuste (wrap) y la alineación de varios ejes de los elementos (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 envía los errores aquí.

Nueva implementación de SlotTable (experimental)

Presentamos una nueva implementación de SlotTable, que está inhabilitada de forma predeterminada en esta versión. SlotTable es la estructura de datos interna que usa el entorno de ejecución de Compose para realizar un seguimiento del estado de tu jerarquía de composición, realizar un seguimiento de las invalidaciones y recomposiciones, almacenar valores recordados y realizar un seguimiento de todos los metadatos de la composición en el entorno de ejecución. Esta nueva implementación está diseñada para mejorar el rendimiento, principalmente en torno a 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 por venir, nunca hubo un mejor momento para migrar a Jetpack Compose. Como siempre, valoramos tus comentarios y solicitudes de funciones (especialmente sobre las funciones de @Experimental que aún están en desarrollo). Envíalos aquí. ¡Feliz compilación!

Escrito por:
Continuar leyendo