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

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

5 минут чтения
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

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

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

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

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

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

Мы также добавили несколько удобных инструментов визуальной отладки для общих элементов и Modifier.animatedBounds . Теперь вы можете точно видеть, что происходит «под капотом» — например, целевые границы, траектории анимации и количество найденных совпадений, — что значительно упрощает выявление причин, по которым переход может вести себя не так, как ожидалось. Чтобы использовать новые инструменты, просто окружите ваш SharedTransitionLayout компонентом 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: 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")
    }
}

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

  • Как было объявлено в сообщении блога 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 для стилизации . API стилей — это новая парадигма для настройки визуальных элементов компонентов, которая традиционно выполнялась с помощью модификаторов. Он разработан для обеспечения более глубокой и простой настройки за счет предоставления стандартного набора стилизуемых свойств с простой стилизацией на основе состояния и анимированными переходами. С этим новым API мы уже видим многообещающие преимущества в производительности . Мы планируем внедрить стили в компоненты Material после стабилизации 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 , которые ещё находятся в разработке) — пожалуйста, отправляйте их сюда . Удачного создания контента!

    Автор:

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