Сегодня мы выпускаем стабильную версию 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,. Если у вас есть собственные детекторы жестов, проверьте их работу с разными типами ввода, включая сенсорные экраны, мыши, сенсорные панели и стилусы, и убедитесь, что поддерживаются колеса прокрутки мыши и жесты на сенсорной панели.
Настройки хоста композиции по умолчанию (среда выполнения 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", ) } }
Ознакомьтесь с документацией и сообщите об ошибках здесь.
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() } }
Вы можете размещать элементы автоматически или явно распределять их по нескольким строкам и столбцам для точности. Самое главное – это высокая адаптивность. Вы можете динамически перенастраивать дорожки и интервалы сетки, чтобы реагировать на состояния устройства, например настольный режим или изменение ориентации. Это гарантирует, что ваш пользовательский интерфейс будет отлично выглядеть на всех форм-факторах.
Ознакомьтесь с документацией и сообщите об ошибках здесь.
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) }) } }
Ознакомьтесь с документацией и сообщите об ошибках здесь.
Новая реализация SlotTable (экспериментальная)
Мы добавили новую реализацию SlotTable, которая по умолчанию отключена в этом выпуске. SlotTable – это внутренняя структура данных, которую среда выполнения Compose использует для отслеживания состояния иерархии композиции, отслеживания недействительности/рекомпозиции, хранения запомненных значений и отслеживания всех метаданных композиции во время выполнения. Новая реализация призвана повысить производительность, в первую очередь при случайных изменениях.
Чтобы попробовать новую версию SlotTable, включите ComposeRuntimeFlags.isLinkBufferComposerEnabled.
Начните программировать уже сегодня!
В Jetpack Compose уже есть много интересных API, и скоро появятся новые. Сейчас самое время перейти на Jetpack Compose. Мы всегда рады вашим отзывам и запросам на добавление функций (особенно @Experimentalтех, которые ещё находятся в разработке). Отправить их можно здесь. Желаем успехов!
-
Новости о продуктахСегодня на Саммите для разработчиков Android мы объявляем о широкой доступности многих инструментов и API, которые помогут вам преодолевать повседневные трудности и дадут больше гибкости при создании отличных приложений для Android.
Matthew McCullough • Время на чтение: 4 минуты -
Новости о продуктахAndroid Studio Rabbit 2 теперь стабильна и готова к использованию в рабочей среде. В этом выпуске представлены ключевые функции, которые помогут вам в разработке, например Bring Your Own Agent, новые функции XR Emulator, обновление LeakCanary, новый инструмент управления навыками агента, код-ревью с помощью ИИ и многое другое.
Matthew Warner • Время на чтение: 3 минуты -
Новости о продуктахПриложения, предназначенные для предстоящего выпуска Android, больше не смогут напрямую записывать данные в контакты с помощью разрешения WRITE_CONTACTS.
Roxanna Aliabadi Walker • Время на чтение: 6 минут
Получайте еженедельную рассылку с последними новостями о разработке для Android.