Новости о продуктах

Что нового в релизе Jetpack Compose от апреля 2026 года?

6 минут чтения
Посмотреть профиль Меган Мехты
Meghan Mehta разработчик-консультант, Android

Сегодня вышел стабильный релиз Jetpack Compose April '26. Этот релиз содержит версию 1.11 основных модулей Compose (см. полное сопоставление BOM ), инструменты отладки общих элементов, события трекпада и многое другое. У нас также есть несколько экспериментальных API, которые мы хотели бы, чтобы вы протестировали и оставили нам отзывы.

Чтобы использовать сегодняшнюю версию, обновите версию Compose BOM до:

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

Изменения в Compose 1.11.0

Выполнение сопрограмм в тестах

We're introducing a major update to how Compose handles test timing. Following the opt-in period announced in Compose 1.10, the v2 testing APIs are now the default, and the v1 APIs have been deprecated. The key change is a shift in the default test dispatcher. While the v1 APIs relied on the UnconfinedTestDispatcher , which executed coroutines immediately, the v2 APIs use the StandardTestDispatcher . This means that when a coroutine is launched in your tests, it is now queued and does not execute until the virtual clock is advanced.

Это лучше имитирует производственные условия, эффективно устраняя состояния гонки и делая ваш набор тестов значительно более надежным и менее нестабильным.

Чтобы ваши тесты соответствовали стандартному поведению сопрограмм и во избежание проблем с совместимостью в будущем, мы настоятельно рекомендуем перенести ваш набор тестов. Ознакомьтесь с нашим подробным руководством по миграции , содержащим информацию о сопоставлении API и распространенных исправлениях.

Улучшения в работе с общими элементами и инструментами анимации.

We've also added some handy visual debugging tools for shared elements and Modifier.animatedBounds . You can now see exactly what's happening under the hood—like target bounds, animation trajectories, and how many matches are found—making it much easier to spot why a transition might not be behaving as expected. To use the new tooling, simply surround your SharedTransitionLayout with the LookaheadAnimationVisualDebugging composable.

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

События сенсорной панели

We've revamped Compose support for trackpads, like built-in laptop trackpads, attachable trackpads for tablets, or external/virtual trackpads. Basic trackpad events will now generally be considered PointerType.Mouse events, aligning mouse and trackpad behavior to better match user expectations. Previously, these trackpad events were interpreted as fake touchscreen fingers of PointerType.Touch , which led to confusing user experiences. For example, clicking and dragging with a trackpad would scroll instead of selecting. By changing the pointer type these events have in the latest release of Compose, clicking and dragging with a trackpad will no longer scroll.

Мы также добавили поддержку более сложных жестов на тачпаде, распознаваемых платформой начиная с API 34, включая свайпы двумя пальцами и масштабирование . Эти жесты автоматически распознаются такими компонентами, как Modifier.scrollable и Modifier.transformable для улучшения взаимодействия с тачпадом.

Эти изменения улучшают работу тачпадов во встроенных компонентах: устранена избыточная неточность сенсорного отклика, добавлен более интуитивно понятный жест начала перетаскивания, двойное и тройное выделение текста в текстовых полях, а также контекстные меню в текстовых полях в стиле рабочего стола.

Для проверки работы тачпада появились новые API тестирования с performTrackpadInput , которые позволяют проверять поведение ваших приложений при использовании с тачпадом. Если у вас есть собственные детекторы жестов, проверьте поведение для разных типов ввода, включая сенсорные экраны, мыши, тачпады и стилусы, и убедитесь в поддержке колесика прокрутки мыши и жестов на тачпаде.

beforeAndAfter.webp

Настройки хоста композиции по умолчанию (среда выполнения Compose)

We introduced HostDefaultProvider , LocalHostDefaultProvider , HostDefaultKey , and ViewTreeHostDefaultKey to supply host-level services directly through compose-runtime. This removes the need for libraries to depend on compose-ui for lookups, better supporting Kotlin Multiplatform. To link these values to the composition tree, library authors can use compositionLocalWithHostDefaultOf to create a CompositionLocal that resolves defaults from the host.

Предварительный просмотр оболочек

Функция пользовательских предварительных просмотров в Android Studio — это новая возможность, позволяющая точно определить, как будет отображаться содержимое предварительного просмотра в Compose.

By implementing the PreviewWrapperProvider interface and applying the new @PreviewWrapper annotation, you can easily inject custom logic, such as applying a specific Theme . The annotation can be applied to a function annotated with @Composable and @Preview or @MultiPreview , offering a generic, easy-to-use solution that works across preview features and significantly reduces repetitive code.

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

Амортизация и удаление

  • As announced in the Compose 1.10 blog post , we're deprecating Modifier.onFirstVisible() . Its name often led to misconceptions, particularly within lazy layouts, where it would trigger multiple times during scrolling. We recommend migrating to Modifier.onVisibilityChanged() , which allows for more precise manual tracking of visibility states tailored to your specific use case requirements.
  • Флаг ComposeFoundationFlags.isTextFieldDpadNavigationEnabled был удален, поскольку навигация с помощью D-pad для TextFields теперь всегда включена по умолчанию. Новое поведение гарантирует, что события D-pad от геймпада или пульта дистанционного управления телевизора сначала перемещают курсор в заданном направлении. Фокус может переместиться на другой элемент только тогда, когда курсор достигнет конца текста.

Будущие API

In the upcoming Compose 1.12.0 release, the compileSdk will be upgraded to compileSdk 37 , with AGP 9 and all apps and libraries that depend on Compose inheriting this requirement. We recommend keeping up to date with the latest released versions, as Compose aims to promptly adopt new compileSdks to provide access to the latest Android features. Be sure to check out the documentation here for more information on which version of AGP is supported for different API levels.

В Compose 1.11.0 следующие API представлены с аннотацией @Experimental , и мы будем рады услышать ваши отзывы по мере их использования в ваших приложениях. Обратите внимание, что @Experimental APIs предоставляются для предварительной оценки и получения обратной связи и могут быть существенно изменены или удалены в будущих релизах.

Стили (экспериментальные)

We are introducing a new experimental foundation API for styling . The Style API is a new paradigm for customizing visual elements of components, which has traditionally been performed with modifiers. It is designed to unlock deeper, easier customization by exposing a standard set of styleable properties with simple state-based styling and animated transitions. With this new API, we're already seeing promising performance benefits . We plan to adopt Styles in Material components once the Style API stabilizes.

Простой пример переопределения стиля фона в состоянии нажатия:

@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

Ознакомьтесь с документацией и сообщайте об ошибках здесь .

MediaQuery (экспериментальная версия)

Новый API mediaQuery предоставляет декларативный и высокопроизводительный способ адаптации пользовательского интерфейса к окружающей среде. Он абстрагирует сложный поиск информации в простые условия внутри UiMediaScope , гарантируя, что перекомпозиция происходит только тогда, когда это необходимо.

With support for a wide range of environmental signals—from device capabilities like keyboard types and pointer precision, to contextual states like window size and posture—you can build deeply responsive experiences. Performance is baked in with derivedMediaQuery to handle high-frequency updates, while the ability to override scopes makes testing and previews seamless across hardware configurations. Previously, to get access to certain device properties — like if a device was in tabletop mode — you'd need to write a lot of boilerplate to do so:

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

Теперь, с помощью UIMediaQuery , вы можете добавить синтаксис mediaQuery для запроса свойств устройства, например, находится ли устройство в режиме настольного компьютера:

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

Ознакомьтесь с документацией и сообщайте об ошибках здесь .

Сетка (экспериментальная)

Grid is a powerful new API for building complex, two-dimensional layouts in Jetpack Compose. While Row and Column are great for linear designs, Grid gives you the structural control needed for screen-level architecture and intricate components without the overhead of a scrollable list. Grid allows you to define your layout using tracks, gaps, and cells, offering familiar sizing options like Dp , percentages, intrinsic content sizes, and flexible "Fr" units.

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

Вы можете размещать элементы автоматически или явно распределять их по нескольким строкам и столбцам для большей точности. Самое главное, это высокая адаптивность — вы можете динамически перенастраивать дорожки и диапазоны сетки в зависимости от состояния устройства, например, режима настольного компьютера или изменения ориентации, обеспечивая превосходный внешний вид пользовательского интерфейса на разных форм-факторах.

Grid.gif

Ознакомьтесь с документацией и сообщайте об ошибках здесь .

FlexBox (экспериментальный)

FlexBox — это контейнер компоновки, разработанный для высокопроизводительных адаптивных пользовательских интерфейсов. Он управляет размерами элементов и распределением пространства в зависимости от доступных размеров контейнера. Он обрабатывает сложные задачи, такие как перенос элементов ( wrap ) и многоосевое выравнивание элементов ( justifyContent, alignItems, alignContent ). Он позволяет элементам увеличиваться ( grow ) или уменьшаться ( shrink ) в размерах, чтобы заполнить контейнер.

@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

Ознакомьтесь с документацией и сообщайте об ошибках здесь .

Новая реализация SlotTable (экспериментальная)

We've introduced a new implementation of the SlotTable , which is disabled by default in this release. SlotTable is the internal data structure that the Compose runtime uses to track the state of your composition hierarchy, track invalidations/recompositions, store remembered values, and track all metadata of the composition at runtime. This new implementation is designed to improve performance, primarily around random edits.

Чтобы опробовать новую SlotTable , включите параметр ComposeRuntimeFlags.isLinkBufferComposerEnabled .

Начните программировать уже сегодня!

В Jetpack Compose так много новых интересных API, и ещё больше появится в будущем, что сейчас самое подходящее время для перехода на Jetpack Compose . Как всегда, мы ценим ваши отзывы и предложения по функциям (особенно по функциям @Experimental , которые ещё находятся в разработке) — пожалуйста, отправляйте их сюда . Удачного создания контента!

    Автор:
    Продолжить чтение