Обновляйте зависимости или сразу всё через BOM файл:
dependencies {
implementation(
platform("androidx.compose:compose-bom-beta:2026.01.00")
)
}#compose #android
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25👎2
🔗 Pull Request в AOSP
#Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥31👍8❤1👎1
Пример использования FlexBoxLayout в Compose
#Compose
// По умолчанию FlexBox работает как Row (FlexDirection.Row).
FlexBox(
modifier = Modifier.fillMaxWidth(),
config = {
direction =
if (constraints.maxWidth < 400.dp.roundToPx()) FlexDirection.Column
else FlexDirection.Row
},
) {
// Этот элемент имеет фиксированный размер
// и не участвует в распределении свободного пространства.
Box(
modifier = Modifier.size(80.dp).background(Color.Magenta),
contentAlignment = Alignment.Center,
) {
Text("Fixed")
}
// Этот элемент имеет коэффициент grow = 1
// и займет 1/3 оставшегося пространства.
Box(
modifier = Modifier
.height(80.dp)
.flex { grow = 1f }
.background(Color.Yellow),
contentAlignment = Alignment.Center,
) {
Text("Grow = 1")
}
// Этот элемент имеет коэффициент grow = 2
// и займет 2/3 оставшегося пространства.
Box(
modifier = Modifier
.height(80.dp)
.flex { grow = 2f }
.background(Color.Green),
contentAlignment = Alignment.Center,
) {
Text("Grow = 2")
}
}
#Compose
🔥22👍9❤5👎2
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍4❤3👎1
🔥 Compose Hot Reload 1.0.0 — стабильный релиз!
JetBrains выпустили стабильную версию Compose Hot Reload, и это действительно круто!
Теперь когда меняете код Compose UI → жмете Cmd+S/Ctrl+S → изменения мгновенно применяются в запущенном приложении. Без перезапуска. Без потери state.
Можно добавлять/удалять функции, классы, параметры — практически любые изменения кода работают.
✅ Стабильная версия 1.0.0 — больше не beta
✅ Отдельный плагин НЕ нужен — встроен в Compose Multiplatform 1.10+, работает из коробки (zero configuration)
⚠️ Работает только на JVM Desktop — и вот почему это важно понять:
Почему только JVM Desktop?
Hot Reload требует JetBrains Runtime с DCEVM (Dynamic Code Evolution VM). Обычная JVM умеет перезагружать только тела методов. DCEVM может делать произвольные изменения кода — добавлять поля в классы, менять иерархию, интерфейсы и т.д.
Android и iOS не могут использовать JetBrains Runtime с DCEVM. Поэтому Hot Reload технически невозможен на этих платформах.
💡 Зачем это мобильным разработчикам?
Еще один повод добавить Desktop таргет в ваш KMP проект!
Даже если вы не планируете запускать Desktop версию в прод - это мощный инструмент для разработки:
👉 Быстро итерируете UI на Desktop с Hot Reload
👉 Проверяете изменения
👉 Переносите на Android/iOS
Скорость итераций UI вырастает в разы. Вместо "изменил → собрал → запустил → дождался" получается "изменил → Cmd+S → увидел результат".
Короче: если делаете Compose Multiplatform — попробуйте обязательно. Desktop таргет окупится только ради Hot Reload.
🔗 Подробности в блоге JetBrains и в документации
#Compose #KMP #Desktop #JVM #CMP
JetBrains выпустили стабильную версию Compose Hot Reload, и это действительно круто!
Теперь когда меняете код Compose UI → жмете Cmd+S/Ctrl+S → изменения мгновенно применяются в запущенном приложении. Без перезапуска. Без потери state.
Можно добавлять/удалять функции, классы, параметры — практически любые изменения кода работают.
✅ Стабильная версия 1.0.0 — больше не beta
✅ Отдельный плагин НЕ нужен — встроен в Compose Multiplatform 1.10+, работает из коробки (zero configuration)
⚠️ Работает только на JVM Desktop — и вот почему это важно понять:
Почему только JVM Desktop?
Hot Reload требует JetBrains Runtime с DCEVM (Dynamic Code Evolution VM). Обычная JVM умеет перезагружать только тела методов. DCEVM может делать произвольные изменения кода — добавлять поля в классы, менять иерархию, интерфейсы и т.д.
Android и iOS не могут использовать JetBrains Runtime с DCEVM. Поэтому Hot Reload технически невозможен на этих платформах.
💡 Зачем это мобильным разработчикам?
Еще один повод добавить Desktop таргет в ваш KMP проект!
Даже если вы не планируете запускать Desktop версию в прод - это мощный инструмент для разработки:
👉 Быстро итерируете UI на Desktop с Hot Reload
👉 Проверяете изменения
👉 Переносите на Android/iOS
Скорость итераций UI вырастает в разы. Вместо "изменил → собрал → запустил → дождался" получается "изменил → Cmd+S → увидел результат".
Короче: если делаете Compose Multiplatform — попробуйте обязательно. Desktop таргет окупится только ради Hot Reload.
🔗 Подробности в блоге JetBrains и в документации
#Compose #KMP #Desktop #JVM #CMP
👍28🔥8👎3❤1
Landscapist — это модульная библиотека для загрузки изображений, построенная специально для Compose. В отличие от монолитных решений, она предлагает гибкую архитектуру с поддержкой различных движков загрузки: Glide, Coil и Fresco.
Ключевые фичи:
👉 Compose Multiplatform из коробки. Библиотека изначально проектировалась для работы на Android, iOS, Desktop и Web. Один API для всех платформ.
👉 Модульная архитектура. Вы подключаете только то, что нужно. Core-модуль весит минимум, а специфичные функции (placeholder, эффекты, анимации) добавляются отдельными зависимостями.
👉 Декларативные модификаторы. Все возможности библиотеки доступны через Compose-модификаторы, что делает код чище и понятнее.
👉 Продвинутая обработка состояний. Встроенная поддержка loading, success, failure с возможностью кастомизации под каждое состояние.
👉 Эффекты и анимации. Circular Reveal, crossfade, shimmer-эффект — всё это доступно out-of-the-box.
👉 Palette API. Автоматическое извлечение цветовой палитры из изображения для создания адаптивного UI.
suspend fun loadImage(url: String) {
val request = ImageRequest.builder()
.model(url)
.size(width = 800, height = 600)
.build()
landscapist.load(request).collect { result ->
when (result) {
is ImageResult.Loading -> {
println("Loading...")
}
is ImageResult.Success -> {
val imageBitmap = result.data
val dataSource = result.dataSource // MEMORY, DISK, or NETWORK
println("Loaded from: $dataSource")
}
is ImageResult.Failure -> {
val error = result.reason
println("Error: ${error.message}")
}
}
}
}📃 Документация
#Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
👍38❤5👎4🤔2
Forwarded from Android Live 🤖
Styles API в Jetpack Compose 🚀
Интересного завезли. В Compose появился экспериментальный API для работы со стилями, который делает их изменение гораздо удобнее.
Сейчас работа с динамическими стилями требует немало ручного труда. И хотя
Ниже приведён пример кнопки, которая меняет цвет при состояниях
Выглядит неплохо, посмотрим, что будет дальше. Детали тут.
Интересного завезли. В Compose появился экспериментальный API для работы со стилями, который делает их изменение гораздо удобнее.
Сейчас работа с динамическими стилями требует немало ручного труда. И хотя
InteractionSource неплохо приспособлен для этих задач, Styles API упрощает процесс в разы.Ниже приведён пример кнопки, которая меняет цвет при состояниях
hovered и pressed.
@Composable
fun InteractiveButton(onClick: () -> Unit) {
ClickableStyleableBox(
onClick = onClick,
style = {
background(Color.Green)
size(150.dp)
hovered { animate { background(Color.Yellow) } }
pressed { animate { background(Color.Red) } }
}
)
}
Выглядит неплохо, посмотрим, что будет дальше. Детали тут.
Dove Letter
Jetpack Compose Style API: Reusable Styles for Composables
How the experimental Compose Style API lets you define reusable, typed style objects for composables. Examples, use cases, and tradeoffs inside.
❤24🔥13👍4👎2
This media is not supported in your browser
VIEW IN TELEGRAM
Анимация смены темы реализована через перехват отрисовки в Modifier.Node: сначала делается снимок UI в старой теме, затем тема переключается, фиксируется новое состояние и запускается анимация между двумя скриншотами. Переход рисуется как круговое раскрытие новой темы, что позволяет избежать мерцаний и добиться плавного эффекта.
#Compose #Анимация
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥88👍11❤5👎5
This media is not supported in your browser
VIEW IN TELEGRAM
Вышел крупный релиз плагина для Android Studio. Две главные фичи:
👉 Recomposition Cascade Visualizer
Правый клик на любой @Composable → "Analyze Recomposition Cascade" — и получаешь дерево всех downstream-компонентов, которые будут перерисованы. Для каждого показывается статус (skippable / non-skippable), общая статистика и максимальная глубина. Двойной клик по узлу — переход к исходнику. Работает с защитой от циклов и ограничением глубины до 10 уровней.
👉 Live Recomposition Heatmap
Прямо в редакторе, над каждой composable-функцией, в реальном времени отображается количество рекомпозиций с подключённого устройства через ADB. Цветовая индикация:
🟢 < 10 — всё ок
🟡 10–50 — стоит присмотреться
🔴 50+ — проблема
Данные читаются из TraceRecomposition событий logcat. Поддерживается несколько устройств одновременно.
#Compose #Performance
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤53👍17👎4🔥3🤔3
Forwarded from Aurora Developers (Vitaliy Zarubin)
🔥 Compose Multiplatform доступен на ОС Аврора!
Отличные новости для Kotlin-сообщества и всех, кто интересуется российской мобильной разработкой. Теперь вы можете создавать приложения для ОС Аврора, используя современный и привычный инструментарий — Kotlin и Compose Multiplatform.
Что опубликовано:
В репозитории на mos.hub выложены компоненты, необходимые для разработки:
- Проекты Compose Multiplatform для сборки.
- Готовые артефакты в репозитории Aurora Maven.
- Плагин для Gradle, упрощающий сборку приложений.
Что дальше?
В планах — расширение поддержки платформы и стабилизация проекта. А уже сейчас в документации вы найдете подробное руководство по началу работы, а также два демонстрационных приложения, которые помогут быстро разобраться с особенностями платформы.
👉 Документация
Хотите помочь проекту стать лучше?
Присоединяйтесь к разработке на mos.hub! Мы открыты к вашему коду и экспертизе. Только #ВМЕСТЕ мы сможем сделать инструмент максимально полезным для всего сообщества.
👉 Репозиторий
Отличные новости для Kotlin-сообщества и всех, кто интересуется российской мобильной разработкой. Теперь вы можете создавать приложения для ОС Аврора, используя современный и привычный инструментарий — Kotlin и Compose Multiplatform.
Что опубликовано:
В репозитории на mos.hub выложены компоненты, необходимые для разработки:
- Проекты Compose Multiplatform для сборки.
- Готовые артефакты в репозитории Aurora Maven.
- Плагин для Gradle, упрощающий сборку приложений.
Что дальше?
В планах — расширение поддержки платформы и стабилизация проекта. А уже сейчас в документации вы найдете подробное руководство по началу работы, а также два демонстрационных приложения, которые помогут быстро разобраться с особенностями платформы.
👉 Документация
Хотите помочь проекту стать лучше?
Присоединяйтесь к разработке на mos.hub! Мы открыты к вашему коду и экспертизе. Только #ВМЕСТЕ мы сможем сделать инструмент максимально полезным для всего сообщества.
👉 Репозиторий
👎49🔥32🤔8👍4❤3
Forwarded from Vitaliy Zarubin | @keygenqt
Please open Telegram to view this post
VIEW IN TELEGRAM
👎44👍27🤔3
Forwarded from Android Broadcast
🤯 Конец Android View ближе чем кажется - в будущей версии Android Studio убирают поддержку превью для Custom View.
Источник - сайт Android Developers
#Android #AndroidDev #Compose #AndroidStudio
Источник - сайт Android Developers
#Android #AndroidDev #Compose #AndroidStudio
👍60🤯42👎18🔥13🎉11🏆1
Мэтт МакКенна выпустил библиотеку, которая превращает рекомпозиции в обычные test assertions. Dejavu решает проблемы постоянного мониторинга за рекомпозияцими без изменений в продакшн-коде — только
Modifier.testTag(), который скорее всего у вас уже есть:// Пример теста
@get:Rule
val composeTestRule = createRecompositionTrackingRule()
@Test
fun incrementCounter_onlyValueRecomposes() {
composeTestRule.onNodeWithTag("inc_button").performClick()
composeTestRule.onNodeWithTag("counter_value")
.assertRecompositions(exactly = 1)
composeTestRule.onNodeWithTag("counter_title")
.assertStable() // ноль рекомпозиций
}
Когда тест падает, получаете структурированный отчёт:
UnexpectedRecompositionsError: testTag='product_header'
Composable: demo.app.ui.ProductHeader (ProductList.kt:29)
Expected: exactly 0 recomposition(s)
Actual: 1 recomposition(s)
All tracked composables:
ProductListScreen = 1
ProductHeader = 1 <-- FAILED
ProductItem = 1
Recomposition timeline:
#1 at +0ms — param slots changed: [1] | parent: ProductListScreen
Possible cause:
1 state change(s) of type Int
Parameter/parent change detected (dirty bits set)
Видно какой composable, сколько раз рекомпозировался и почему. Под капотом используется
CompositionTracer API из compose-runtime 1.2.0, никаких Gradle-плагинов и байткод-манипуляций. Запускается как instrumented тест.#Android #AndroidDev #Compose #JetpackCompose
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥48👏7❤5👎4🤔2👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Наткнулся на отличный разбор от ребят из Т-Банка — они переписывали главный экран с XML+View на Compose и столкнулись с проблемой, которую многие, думаю, обходят стороной.
Суть: есть
LazyColumn, в нём элемент с animateContentSize(). Когда элемент расширяется по высоте, нижние карточки не успевают сместиться в такт — небольшой, но заметный рассинхрон.Казалось бы — поменяй
spring на tween, синхронизируй тайминги и готово. Спойлер: нет.1️⃣ Замена на линейный
tween — разницы визуально почти ноль. Скорость placementSpec тоже не влияет на смещение нижних айтемов при ресайзе верхнего.2️⃣ Установка
placementSpec = null — синхронизация появляется, но полностью ломает анимацию перемещения айтемов. Не вариант.3️⃣ Попытка написать свой модификатор — обречена с самого начала.
LazyLayoutAnimationSpecsNode помечен как internal, а внутренний LazyLayoutItemAnimator, который реально управляет анимациями, недоступен снаружи. Скопировать код не выйдет — каст по типу вернёт null, и вся механика рассыпается. Форкать 5000+ строк LazyColumn — очевидно нет.Самое интересное — анимация удаления при кастомной реализации не работает в принципе: к моменту
DisposableEffect.onDispose элемент уже удалён из дерева. А стандартный animateItem работает на уровне layout-фазы и может буквально «удерживать» элемент в дереве до окончания анимации.Итог у команды — оставили
RecyclerView для списка, айтемы внутри на Compose. Костыль, но рабочий, пока Google не откроет нужные API. Issue уже создан, подписывайтесь если сталкивались.Я лично не сталкивался с таким кейсом в продакшне, но статья хорошо показывает, где у Compose сейчас реальные границы расширяемости и что без View пока никуда.
#Android #Compose #AndroidDev #JetpackCompose #Анимация
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥37👎13❤8👍2
Одна из моих любимых тем в Compose-разработке — отладка рекомпозиций. Layout Inspector, Rebugger, ComposeInvestigator — всё это хорошие инструменты, но у них общий слепой угол: они говорят сколько рекомпозиций, но не отвечают на вопрос нормально ли это для данного компонента.
HomeScreen, который рекомпозируется 10 раз в секунду — это проблема. Анимация, которая делает то же самое — это норма. Число одинаковое, вывод противоположный.Библиотека работает на основе Kotlin compiler plugin, который классифицирует каждый
@Composable по роли и назначает ему бюджет рекомпозиций:1️⃣ Screen — 3/s. Если экранный компонент рекомпозируется чаще, state утекает вверх по дереву
2️⃣ Leaf — 5/s.
Text, Icon, Image — дёшевы сами по себе, но не должны «молотить»3️⃣ Animated — 120/s. Всё, что использует
animate*, Transition, Animatable — пусть работает4️⃣ Container — 10/s, Interactive — 30/s, List Item — 60/s
При скролле бюджеты удваиваются, при анимации и вводе — умножаются на 1.5. Контекст учитывается.
Когда что-то выходит за рамки, в логах появляется не просто число, а конкретика:
BUDGET VIOLATION: ProfileHeader rate=11/s exceeds LEAF budget=5/s
-> params: avatarUrl=CHANGED, displayName=CHANGED
-> forced: 0 | param-driven: 11 | interaction: IDLE
@Composable. Никакого переключения контекста.Попробую на своих проектах (только не отправляй в прод) — идея с контекстными бюджетами кажется мне намного честнее, чем единый порог для всех компонентов. Решение пока не достигло версии 1.0 но это и некритично, так как не влияет на продакшен код.
🔗 Источник: adital.dev
#Android #Compose #AndroidDev #Производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤49👍13👎8