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

Что нового в выпуске Jetpack Compose за апрель 2026 г.

Время на чтение: 6 минут
Посмотреть профиль пользователя Meghan Mehta
Meghan Mehta Специалист по связям с разработчиками Android

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

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

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

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

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

Мы представляем крупное обновление, которое меняет то, как Compose обрабатывает время тестирования. После периода добровольного перехода, объявленного в Compose 1.10, API тестирования версии 2 теперь используются по умолчанию, а API версии 1 устарели. Ключевым изменением является переход на диспетчер тестов по умолчанию. В API версии 1 использовался UnconfinedTestDispatcher, который немедленно выполнял сопрограммы, а в API версии 2 используется StandardTestDispatcher. Это означает, что когда сопрограмма запускается в ваших тестах, она теперь ставится в очередь и не выполняется до тех пор, пока виртуальные часы не будут переведены вперед.

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

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

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

Мы также добавили удобные инструменты визуальной отладки для общих элементов и Modifier.animatedBounds. Теперь вы можете точно видеть, что происходит за кулисами, например границы целей, траектории анимации и количество найденных совпадений. Это значительно упрощает поиск причин, по которым переход может работать не так, как ожидалось. Чтобы использовать новые инструменты, просто окружите SharedTransitionLayout composable-функцией LookaheadAnimationVisualDebugging.

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

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

Мы обновили поддержку сенсорных панелей в Compose. Теперь она работает со встроенными панелями ноутбуков, подключаемыми панелями планшетов, а также внешними и виртуальными панелями. Базовые события сенсорной панели теперь будут считаться событиями PointerType.Mouse. Это позволит привести поведение мыши и сенсорной панели в соответствие с ожиданиями пользователей. Раньше такие события интерпретировались как ложные касания сенсорного экрана (PointerType.Touch), что приводило к ошибкам. Например, если вы нажмете на сенсорную панель и проведете по ней пальцем, то прокрутите страницу, а не выделите текст. В последней версии Compose мы изменили тип указателя для этих событий, и теперь нажатие и перетаскивание на сенсорной панели не приводит к прокрутке.

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

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

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

beforeAndAfter.webp

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

Мы добавили HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey и ViewTreeHostDefaultKey, чтобы предоставлять сервисы на уровне хоста напрямую через compose-runtime. Это избавляет библиотеки от необходимости зависеть от compose-ui для поиска, что улучшает поддержку Kotlin Multiplatform. Чтобы связать эти значения с деревом композиции, авторы библиотек могут использовать compositionLocalWithHostDefaultOf для создания CompositionLocal, который разрешает значения по умолчанию от хоста.

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

Пользовательские предварительные просмотры Android Studio – это новая функция, которая позволяет точно определить, как отображается содержимое предварительного просмотра Compose.

Реализовав интерфейс PreviewWrapperProvider и применив новую аннотацию @PreviewWrapper, вы можете легко внедрить собственную логику, например применить определенный Theme. Ее можно применить к функции, аннотированной с помощью @Composable и @Preview или @MultiPreview. Это универсальное и простое решение, которое работает с предварительными версиями функций и значительно сокращает повторяющийся код.

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

Прекращение поддержки и удаление

  • Как мы сообщали в записи блога о Compose 1.10, поддержка Modifier.onFirstVisible() прекращается. Его название часто приводило к неправильному пониманию, особенно в ленивых макетах, где оно срабатывало несколько раз во время прокрутки. Рекомендуем перейти на Modifier.onVisibilityChanged(), который позволяет точнее отслеживать состояния видимости вручную в соответствии с вашими требованиями.
  • Параметр ComposeFoundationFlags.isTextFieldDpadNavigationEnabled удален, поскольку навигация с помощью D-pad для TextFields теперь всегда включена по умолчанию. В новом поведении события D-pad от геймпада или пульта телевизора сначала перемещают курсор в заданном направлении. Фокус можно переместить на другой элемент, только когда курсор достигнет конца текста.

Будущие API

В предстоящем выпуске Compose 1.12.0 compileSdk будет обновлен до compileSdk 37 с AGP 9. Все приложения и библиотеки, зависящие от Compose, унаследуют это требование. Рекомендуем использовать актуальные версии, поскольку Compose стремится оперативно внедрять новые compileSdks, чтобы предоставлять доступ к последним функциям Android. Обязательно ознакомьтесь с документацией, чтобы узнать, какие версии AGP поддерживаются для разных уровней API. 

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

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

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

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

@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, обеспечивая рекомпозицию только при необходимости.

Поддержка широкого спектра сигналов среды – от возможностей устройства, таких как типы клавиатуры и точность указателя, до контекстных состояний, таких как размер окна и положение, – позволяет создавать глубоко адаптивные интерфейсы. derivedMediaQuery обеспечивает высокую производительность при частых обновлениях, а возможность переопределять области действия упрощает тестирование и предварительный просмотр на разных аппаратных конфигурациях. Раньше, чтобы получить доступ к определенным свойствам устройства, например узнать, находится ли оно в настольном режиме, нужно было написать много шаблонного кода: 

@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 – это новый мощный API для создания сложных двумерных макетов в Jetpack Compose. Row и Column отлично подходят для линейных макетов, а Grid позволяет управлять структурой, необходимой для архитектуры на уровне экрана и сложных компонентов, без лишних затрат на прокручиваемый список. Grid позволяет определять макет с помощью дорожек, промежутков и ячеек, предлагая привычные варианты размеров, такие как Dp, проценты, внутренние размеры контента и гибкие единицы "Fr".

@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 (экспериментальная)

Мы добавили новую реализацию SlotTable, которая по умолчанию отключена в этом выпуске. SlotTable – это внутренняя структура данных, которую среда выполнения Compose использует для отслеживания состояния иерархии композиции, отслеживания недействительности/рекомпозиции, хранения запомненных значений и отслеживания всех метаданных композиции во время выполнения. Новая реализация призвана повысить производительность, в первую очередь при случайных изменениях.

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

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

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

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