Что нового:
Compose iOS
👉 Прокачали работу с софт клавиатурой
Compose Desktop:
👉 Compose Hot Reload теперь теперь часть Compose. Больше не нужна отдельная зависимость
👉 SwingPanel теперь автоматически подстраивает свой размер на основе размеров контента в ней
Gradle плагин:
👉 Алиасы для Compose зависимостей в Gradle теперь не рекомендуютя к использованию. Подключаем артефакты как и все другие
👉 Поддержка Android Gradle Plugin 9.0.0
#compose #cmp #gradle #ios #desktop
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥3👏1
🤯 Liquid Glass в iOS 26 — удар по кроссплатформенным UI: Compose и Flutter
В iOS 26 Apple полностью обновила визуальный язык всех своих систем — от iPhone до Mac — на основе эффекта Liquid Glass.
Это не просто редизайн: весь интерфейс теперь основан на динамическом материале, который выглядит как живое стекло — с прозрачностью, преломлением, отражениями и адаптацией к фону и движению.
🧩 Всё это работает на уровне системного UI-стека, а не через отдельные шейдеры в приложении.
Apple интегрировала эффект прямо в UIKit и SwiftUI — стандартные контролы (панели, навигация, вкладки, кнопки и т.д.) автоматически наследуют материал без изменений в коде.
Для кастомных интерфейсов появились обновлённые API, управляющие степенью «стеклянности» и размытия.
Рендеринг выполняется через Metal с аппаратным ускорением и оптимизацией под энергопотребление.
⚙️ Compose Multiplatform и Flutter рендерят интерфейс поверх собственного движка — Skia и Impeller соотвественно, который полностью берёт на себя отрисовку.
Это значит, что системные визуальные эффекты, вроде динамического стекла, не будут работать «из коробки».
Возможна имитация Liquid Glass силами движка, но тогда нужно в реальном времени искажать фон под элементом — а это серьёзная нагрузка на CPU/GPU и батарею.
😯 На iOS Skia действительно работает поверх Metal, но использует лишь его базовый 2D-функционал, без доступа к системным шейдерам, материалам и эффектам среды.
Теоретически Skia может эволюционировать в эту сторону, но пока она изолирована от системного рендеринга.
🤖 На Android у Jetpack Compose ситуация лучше: он использует не отдельный движок, а системный рендер Android View, поэтому интеграция системных эффектов возможна нативно.
На iOS же для Compose Multiplatform всё зависит от будущих решений JetBrains — если появится рендер поверх UIKit/Metal, тогда можно будет подключать нативные материалы.
Пока же оптимальный вариант — использовать SwiftUI для UI и KMP-модули для бизнес-логики.
🎯 Apple подняла планку того, что значит «feels like native».
Теперь визуальное и интерактивное поведение невозможно подделать одной лишь кастомной отрисовкой — нужна полная интеграция с системным стеком.
#apple #ios #compose #flutter
В iOS 26 Apple полностью обновила визуальный язык всех своих систем — от iPhone до Mac — на основе эффекта Liquid Glass.
Это не просто редизайн: весь интерфейс теперь основан на динамическом материале, который выглядит как живое стекло — с прозрачностью, преломлением, отражениями и адаптацией к фону и движению.
🧩 Всё это работает на уровне системного UI-стека, а не через отдельные шейдеры в приложении.
Apple интегрировала эффект прямо в UIKit и SwiftUI — стандартные контролы (панели, навигация, вкладки, кнопки и т.д.) автоматически наследуют материал без изменений в коде.
Для кастомных интерфейсов появились обновлённые API, управляющие степенью «стеклянности» и размытия.
Рендеринг выполняется через Metal с аппаратным ускорением и оптимизацией под энергопотребление.
Это значит, что системные визуальные эффекты, вроде динамического стекла, не будут работать «из коробки».
Возможна имитация Liquid Glass силами движка, но тогда нужно в реальном времени искажать фон под элементом — а это серьёзная нагрузка на CPU/GPU и батарею.
😯 На iOS Skia действительно работает поверх Metal, но использует лишь его базовый 2D-функционал, без доступа к системным шейдерам, материалам и эффектам среды.
Теоретически Skia может эволюционировать в эту сторону, но пока она изолирована от системного рендеринга.
На iOS же для Compose Multiplatform всё зависит от будущих решений JetBrains — если появится рендер поверх UIKit/Metal, тогда можно будет подключать нативные материалы.
Пока же оптимальный вариант — использовать SwiftUI для UI и KMP-модули для бизнес-логики.
🎯 Apple подняла планку того, что значит «feels like native».
Теперь визуальное и интерактивное поведение невозможно подделать одной лишь кастомной отрисовкой — нужна полная интеграция с системным стеком.
#apple #ios #compose #flutter
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯34👍12❤1🔥1🤔1
Это изменение позволяет использовать нативные UIView из iOS с прозрачным фоном и использовать все нативные шейдеры! Но это все также встраивание элементов из нативного механизма отрисовки в Compose, аналогично как это есть для Android и Swing компонентов в iOS.
Фактически для Compose Button сделать liquid glass эффект не получится сделать. Для этого надо делать обертку на стандартным компонентов из iOS.
Спасибо @nek_12 за подсвечивание момента
#compose #ios26
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32❤2🤔1
Media is too big
VIEW IN TELEGRAM
Compose позволяет разрабатывать под все актуальные Android платформы, повышая удобство и скорость реализации. Подробности в докладе от Google
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤3🤔1
В Compose есть возможность настраивать размер кэша для lazy layouts! Можно контролировать, сколько элементов сохранять до и после видимой области.
Что изменилось?
👉 До версии 1.9: Lazy списки компилировали только 1 элемент вперед и сразу удаляли невидимые
👉 С версии 1.9: Можно задать точное количество сохраняемых элементов в dp или % viewport
Зачем это нужно?
✅ Увеличивает плавность прокрутки за счет подготовки контента заранее
✅ Оптимизирует использование pausable composition между кадрами
✅ Позволяет балансировать между памятью и производительностью
Как использовать:
// Кэш в dp
val dpCacheWindow = LazyLayoutCacheWindow(
ahead = 150.dp, // 150dp вперед
behind = 100.dp // 100dp назад
)
// Или в процентах от viewport
val percentCacheWindow = LazyLayoutCacheWindow(
ahead = 0.5f, // 50% viewport вперед
behind = 0.3f // 30% viewport назад
)
val state = rememberLazyListState(cacheWindow = dpCacheWindow)
LazyColumn(state = state) {
// ваш контент
}
Рекомендации:
🎯 Начинайте с 50% viewport и тестируйте производительность
🎯 Для тяжелых элементов используйте больший кэш
🎯 Для легких списков можно уменьшить значения
Особенно полезно для сложных списков с изображениями, анимациями или тяжелой бизнес-логикой!
#Compose #Производительность #cmp
Please open Telegram to view this post
VIEW IN TELEGRAM
❤48👍17🔥4
Традиционно измерение и кэширование текста происходит на UI-потоке, что для длинных текстов может создавать задержки. Начиная с версии 1.9, Compose позволяет вынести эти операции в фоновый поток. Для View уже давно была такая возможность, а вот на Compose ждали.
Как это работает на практике:
val textMeasurementExecutor = Executors.newSingleThreadExecutor()
CompositionLocalProvider(
LocalBackgroundTextMeasurementExecutor provides DefaultTextMeasurementExecutor
) {
// Весь текст внутри будет предзагружаться в фоне
Column {
Text("Заголовок")
Text("Длинный описательный текст...")
AnnotatedString("Форматированный текст")
}
}
Ключевые преимущества:
- Ускорение layout — предзаполнение word-cache происходит заранее
- Разгрузка UI-потока — тяжелые операции с текстом уходят в фон
- Особенно эффективно в списках (LazyColumn/LazyRow) с текстовым контентом
- Работает с любыми текстовыми компонентами — BasicText, Text, AnnotatedString
Когда стоит применять:
- Приложения с большими объемами текста (читалки, новости, документация)
- Списки с множеством текстовых элементов
- Сложные текстовые интерфейсы с форматированием
❗️Важный нюанс: Результаты могут варьироваться в зависимости от контента, поэтому всегда тестируйте производительность до и после внедрения.
Уже используете эту возможность? Делитесь результатами в комментариях!
#Compose #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
❤31👍10🔥4
Google представила Navigation 3 — совершенно новую библиотеку для навигации в Compose, где управление стеком экранов сводится к простым операциям с списком.
Хорошая новость: JetBrains уже адаптировали её для Compose Multiplatform! В статье на реальном примере показывает, как:
👉 Добавить зависимости Navigation 3 в KMP-проект
👉 Определить маршруты через sealed-интерфейсы с @Serializable
👉 Работать с back stack как с обычным mutable list
👉 Создать адаптивные layouts для разных размеров экранов
Особенно полезно будет:
В статье — чистый код из commonMain с примерами навигации между экранами и реализацией bottom navigation.
#compose #cmp #kmp
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥31👍7
#compose #cmp #kmp #androidjetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤4🔥4
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍23❤2
Появилась реализация навигации под Web-браузер, совместимая с Jetpack Navigation 3 и интегрированная с нативной историей браузера. Автор — Костя Цховребов из JetBrains (KMP-команда).
Теперь Web-приложения на Compose Multiplatform могут работать с привычным поведением браузера: кнопки Back/Forward, корректное управление историей, восстановление состояния и предсказуемая работа нескольких экранов.
Поддерживаются две стратегии навигации:
👉 Chronological - Классическая браузерная модель: линейный переход по посещённым состояниям (Back/Forward).
👉 Hierarchical - Мобильная модель навигации, имитирующая структуру экранов и вложенную иерархию — аналогично Android-приложениям.
🧪 Обе стратегии можно сравнить в онлайн-демо
Пример использования Chronological-навигации
@Composable
fun App() {
val backStack = remember { mutableStateListOf<Any>(Root) }
ChronologicalBrowserNavigation(
backStack = backStack,
saveKey = { key ->
when (key) {
is Root -> buildBrowserHistoryFragment("root")
is Profile -> buildBrowserHistoryFragment(
"profile",
mapOf("id" to key.id.toString())
)
else -> null
}
},
restoreKey = { fragment ->
when (getBrowserHistoryFragmentName(fragment)) {
"root" -> Root
"profile" -> Profile(
getBrowserHistoryFragmentParameters(fragment)
.getValue("id")
?.toInt() ?: error("id is required")
)
else -> null
}
}
)
NavDisplay(backStack) { /* ... */ }
}
Navigation3 Browser кажется важным шагом для формирования единой модели навигации в Compose Multiplatform: Android → Desktop → Web.
Это упростит мультиплатформенную архитектуру и сделает перенос логики между платформами гораздо чище.
#Kotlin #Compose #KMP #CMP #WEB #AndroidJetpack #Jetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17👍11🔥3🤔3
🔥 Remote Compose — новый взгляд на Server-Driven UI в Jetpack Compose
В AndroidX Jetpack появилась новая экспериментальная библиотека
Remote Compose позволяет создавать и рендерить интерфейсы Jetpack Compose удалённо, без пересборки и релиза приложения.
UI генерируется на сервере, сериализуется в компактный бинарный документ и воспроизводится на устройстве.
Remote Compose открывает возможности, которые раньше требовали релиза приложения:
⚡️ Мгновенные A/B-тесты — вариации интерфейса меняются на сервере, без обновлений.
🎨 Обновление дизайна в реальном времени — карточки товаров, баннеры, сезонные темы.
📰 Динамические контентные экраны — новости, акции, спецпроекты, которые появляются мгновенно.
🧪 Фичи без мусора — нет необходимости тянуть все варианты экрана в бинарник.
Архитектура Remote Compose состоит из двух частей:
1️⃣ Создание документа
На сервере вы пишете обычные composable-функции — либо используете специальные Remote* элементы (RemoteColumn, RemoteText и др.).
Библиотека перехватывает draw-операции Compose и превращает UI в бинарный документ. Получается самодостаточный «UI-файл», который можно отправить на клиент.
2️⃣ Воспроизведение документа
На устройстве этот документ «проигрывается» плеером:
👉 есть Compose-плеер — для современных приложений;
👉 есть Android View-плеер — для старых архитектур.
Плеер интерпретирует более 90 низкоуровневых операций (рисование, layout, модификаторы, state), обеспечивая реальную нативную отрисовку, без WebView и без компонентов, которые нужно заранее описывать в приложении.
Почему это лучше JSON или WebView
❌ JSON-подход требует схем, ограничивает сложные эффекты, анимации и кастомные компоненты.
❌ WebView — это отдельный процесс, разная визуальная стилистика, тяжёлое потребление памяти и уязвимости
Remote Compose передаёт не структуру компонентов, а реальные команды рисования. Поэтому любое, самое сложное Compose-UI — будет воспроизведено точно так, как вы его задали.
Базовые принципы Remote Compose
👉 Документность — UI становится бинарным документом, который можно кешировать, версионировать, отправлять по сети.
👉 Платформенная независимость — один документ можно рендерить на телефоне, планшете, складном устройстве и даже часах.
👉 Отделение визуального уровня от логики — клиенту не нужно знать о ваших composable-функциях, ViewModel, DI и т.п.
👉 Двусторонняя связь — клики и события возвращаются на клиент, который решает, что делать (навигировать, логировать, изменять состояние).
👉 Поддержка анимаций и выражений — значения могут вычисляться по времени, переменным, условиям.
Для большинства приложений оптимальная модель — гибридная:
📱 основная навигация + критические экраны в “локальном Compose”,
⚙️ динамические зоны — через Remote Compose.
Если Remote Compose будет развиваться так же активно, как Compose в своё время, это может стать стандартом для динамических интерфейсов на Android. Как вам такой поворот с Compose?
Источник тут
#jetpack #android #compose #serverdrivenui #sdui #bdui
В AndroidX Jetpack появилась новая экспериментальная библиотека
androidx.compose.remote (пока еще даже на dev версия). Она предлагает совершенно другой подход к динамическим интерфейсам и может радикально изменить то, как мы обновляем UI в продакшене, категорически отличающаяся от текущих BDUI/SDUI решений.Remote Compose позволяет создавать и рендерить интерфейсы Jetpack Compose удалённо, без пересборки и релиза приложения.
UI генерируется на сервере, сериализуется в компактный бинарный документ и воспроизводится на устройстве.
Remote Compose открывает возможности, которые раньше требовали релиза приложения:
⚡️ Мгновенные A/B-тесты — вариации интерфейса меняются на сервере, без обновлений.
🎨 Обновление дизайна в реальном времени — карточки товаров, баннеры, сезонные темы.
📰 Динамические контентные экраны — новости, акции, спецпроекты, которые появляются мгновенно.
🧪 Фичи без мусора — нет необходимости тянуть все варианты экрана в бинарник.
Архитектура Remote Compose состоит из двух частей:
1️⃣ Создание документа
На сервере вы пишете обычные composable-функции — либо используете специальные Remote* элементы (RemoteColumn, RemoteText и др.).
Библиотека перехватывает draw-операции Compose и превращает UI в бинарный документ. Получается самодостаточный «UI-файл», который можно отправить на клиент.
2️⃣ Воспроизведение документа
На устройстве этот документ «проигрывается» плеером:
👉 есть Compose-плеер — для современных приложений;
👉 есть Android View-плеер — для старых архитектур.
Плеер интерпретирует более 90 низкоуровневых операций (рисование, layout, модификаторы, state), обеспечивая реальную нативную отрисовку, без WebView и без компонентов, которые нужно заранее описывать в приложении.
Почему это лучше JSON или WebView
❌ JSON-подход требует схем, ограничивает сложные эффекты, анимации и кастомные компоненты.
❌ WebView — это отдельный процесс, разная визуальная стилистика, тяжёлое потребление памяти и уязвимости
Remote Compose передаёт не структуру компонентов, а реальные команды рисования. Поэтому любое, самое сложное Compose-UI — будет воспроизведено точно так, как вы его задали.
Базовые принципы Remote Compose
👉 Документность — UI становится бинарным документом, который можно кешировать, версионировать, отправлять по сети.
👉 Платформенная независимость — один документ можно рендерить на телефоне, планшете, складном устройстве и даже часах.
👉 Отделение визуального уровня от логики — клиенту не нужно знать о ваших composable-функциях, ViewModel, DI и т.п.
👉 Двусторонняя связь — клики и события возвращаются на клиент, который решает, что делать (навигировать, логировать, изменять состояние).
👉 Поддержка анимаций и выражений — значения могут вычисляться по времени, переменным, условиям.
Для большинства приложений оптимальная модель — гибридная:
Если Remote Compose будет развиваться так же активно, как Compose в своё время, это может стать стандартом для динамических интерфейсов на Android. Как вам такой поворот с Compose?
Источник тут
#jetpack #android #compose #serverdrivenui #sdui #bdui
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥92🤯39❤18🤔3👍2
// Пример создания документа на севере
val document = captureRemoteDocument(
context = context,
creationDisplayInfo = displayInfo,
profile = profile
) {
RemoteColumn(modifier = RemoteModifier.fillMaxSize()) {
RemoteText("Dynamic Content")
RemoteButton(onClick = { /* action */ }) {
RemoteText("Click Me")
}
}
}
// Пример воспроизведения документа на клиенте
@Composable
fun DynamicScreen(document: CoreDocument) {
RemoteDocumentPlayer(
document = document,
documentWidth = screenWidth,
documentHeight = screenHeight,
modifier = Modifier.fillMaxSize(),
onNamedAction = { name, value, stateUpdater ->
// Обработка именнового действия из документа
when (name) {
"addToCart" -> cartManager.addItem(value)
"navigate" -> navController.navigate(value)
"trackEvent" -> analytics.logEvent(value)
}
},
bitmapLoader = rememberBitmapLoader() // Для загрузки картинок
)
}
Источник тут
#jetpack #android #compose #serverdrivenui #sdui #bdui
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯32👍8🔥2🤔1
👉 Стабильное API Shared Transition
👉 Оптимизированный скролл
👉 Новые подходы к сохранению данных при пересоздании Activity через ViewModel
🚀 Повышена производительность UI на Compose
🛠 Исправлено багов и шероховатостей
Изменений действительно много — в один пост всё не поместить.
Буду разбирать ключевые обновления по отдельности в следующих публикациях на @compose_broadcast ✨
#compose #android
Please open Telegram to view this post
VIEW IN TELEGRAM
❤21👍3
Важное изменение в Compose 1.10: pausable composition в lazy prefetch теперь включен по умолчанию. Это фундаментальное улучшение в работе runtime, которое значительно уменьшает лаги при сложных UI-нагрузках.
Раньше композиция, раз начавшись, должна была выполниться до конца. Если она была сложной (много элементов, тяжелые вычисления), это могло заблокировать главный поток дольше, чем длится один кадр и получали Freeze Frame и визуальные лаги скролла.
Теперь Compose Runtime может приостанавливать работу, если время на отрисовку кадра заканчивается, и продолжить её в следующем интервале. Особенно эффективно это работает в связке с предзагрузкой (prefetch) ленивых списков.
🔄 Как это работает с Lazy layouts:
// Увеличиваем окно кэша для большего пространства предзагрузки
val cacheWindow = LazyLayoutCacheWindow(
ahead = 0.5f, // 50% вперед
behind = 0.3f // 30% назад
)
val state = rememberLazyListState(cacheWindow = cacheWindow)
LazyColumn(state = state) {
items(heavyItems) { item ->
HeavyComposable(item) // Теперь не заблокирует UI
}
}
🎯 Ключевые преимущества:
1. Плавная прокрутка — даже с тяжелыми элементами
2. Композиция подстраивается под время для отрисовки кадра — композиция «уступает» место другим операциям
3. Никакой сложной настройки — не требует изменения кода приложения
Эта оптимизация — часть продолжающейся работы Google над производительностью Compose. Уже пробовали? Делитесь наблюдениями в комментариях!
#Compose #Производительность #AndroidDev #JetpackCompose
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41🔥15❤5
🎭 Динамическое управление shared element анимациями в Compose
В Compose 1.10.0 вы можете динамически включать и отключать анимации shared element в зависимости от условий навигации или состояния UI. Это особенно полезно, когда нужно анимировать переход только в определенных сценариях.
Раньше
⚠️ Важно: По умолчанию, если shared element отключается во время анимации, текущая анимация завершается до удаления элемента. Это предотвращает резкие обрывы.
Новая фича даёт разработчикам больше контроля над анимациями, делая интерфейсы более предсказуемыми и оптимизированными.
#Compose #AndroidDev #Анимация #UI
В Compose 1.10.0 вы можете динамически включать и отключать анимации shared element в зависимости от условий навигации или состояния UI. Это особенно полезно, когда нужно анимировать переход только в определенных сценариях.
Раньше
sharedElement() и sharedBounds() автоматически анимировали изменения layout при нахождения совпадению по ключу. Теперь можно контролировать эту анимацию через конфигурацию SharedContentConfig.
// отим анимировать переход только с экрана A на экран B, но не обратно
SharedTransitionLayout {
val transition = updateTransition(currentState)
transition.AnimatedContent { targetState ->
// Конфигурация, зависящая от состояния
fun animationConfig(): SharedTransitionScope.SharedContentConfig {
return object : SharedTransitionScope.SharedContentConfig {
override val SharedTransitionScope.SharedContentState.isEnabled: Boolean
get() = transition.currentState == "A" &&
transition.targetState == "B"
}
}
...
}
}
⚠️ Важно: По умолчанию, если shared element отключается во время анимации, текущая анимация завершается до удаления элемента. Это предотвращает резкие обрывы.
Новая фича даёт разработчикам больше контроля над анимациями, делая интерфейсы более предсказуемыми и оптимизированными.
#Compose #AndroidDev #Анимация #UI
👍7
Compose 1.10 представляет новую функцию
retain, которая заполняет важный пробел между существующими API управления состоянием. Теперь можно сохранять объекты между изменениями конфигурации без необходимости их сериализации!-
remember — сохраняет между рекомпозициями ❌ смена конфигурации-
rememberSavable — сохраняет между пересозданиями активити ⚠️ требует сериализации-
retain — сохраняет при смене конфигурации ✅ без сериализации ❌ не работает при убийстве процесса@Composable
fun MediaPlayer() {
val applicationContext = LocalContext.current.applicationContext
// ExoPlayer будет сохранен при повороте экрана
val exoPlayer = retain {
ExoPlayer.Builder(applicationContext)
.setSeekBackIncrementMs(5000)
.setSeekForwardIncrementMs(5000)
.build()
}
// Воспроизведение не прервется при смене конфигурации
DisposableEffect(Unit) {
onDispose { exoPlayer.release() }
}
// ...
}
Под капотом сохранение объекта происходит через механизм ViewModel и имеет такой же цикл жизни
Фича разработана при активном участии AndroidDev-сообщества, особенно команды Circuit. Отличный пример того, как обратная связь разработчиков влияет на развитие платформы!
#Compose #AndroidDev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥59👍11❤5