Да, у нас уже есть Jetpack Navigation 3 с официальной поддержкой KMP. Тем не менее авторы Kompass смотрят на проблему иначе, и идея тут любопытная.
Суть в том, что вся навигация строится на чистых редукторах. Любой переход — это
State + Command → State, без побочных эффектов. Вот как это выглядит в коде:// Граф описывает, какие экраны в нём живут и как рендерятся
class MainNavigationGraph : NavigationGraph {
override fun canResolveDestination(id: String) =
id in setOf("home", "profile")
@Composable
override fun Content(entry: BackStackEntry, destination: Destination, navController: NavController) {
when (destination) {
is MainDestination.Home -> HomeScreen(navController)
is MainDestination.Profile -> ProfileScreen(navController)
}
}
}
// Хост принимает список графов и рендерит текущий экран
@Composable
fun AppNavigation() {
val navController = rememberNavController(
startDestination = MainDestination.Home
)
KompassNavigationHost(
navController = navController,
graphs = persistentListOf(MainNavigationGraph())
)
}
// Навигация из экрана
navController.navigate(
entry = BackStackEntry(destinationId = "profile", scopeId = newScope())
)
// Возврат с результатом
navController.pop(result = ProfileResult(userId = "123"))
NavigationState и BackStackEntry иммутабельны, поэтому всю навигацию можно покрыть обычными unit-тестами без инструментации: создаёшь NavigationHandler, кидаешь команду, проверяешь стейт.Особенности:
👉 Таргеты — Android, iOS, Desktop (JVM).
👉 Scopes вместо ViewModel.
rememberScoped<T> живёт ровно пока BackStackEntry в стеке, автоматически чистится при pop.👉 Multi-graph. Несколько независимых графов с собственными лейаутами. Из коробки есть поддержка master-detail для планшетов.
👉 Дип-линки. Через
DeepLinkHandler — типизированный парсинг URI в NavigationCommand.🛠 Библиотека ещё в активной разработке
#KMP #ComposeMultiplatform #Navigation #Kotlin #AndroidDev
Please open Telegram to view this post
VIEW IN TELEGRAM
👎31👍9
Если composable нужен только для превью из другого модуля,
internal не поможет. Зато поможет кастомная аннотация поверх @RequiresOptIn с уровнем ERROR.kotlin@PreviewOnly
@Composable
fun renderScreenPreviewer(list: List) {
renderList(list)
}
@RequiresOptIn(
message = "This composable is intended for preview usage only",
level = RequiresOptIn.Level.ERROR
)
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FUNCTION)
annotation class PreviewOnly
Теперь любой, кто попробует вызвать его в продакшн коде без
@OptIn(PreviewOnly::class), получит ошибку компиляции, а не warning.Небольшой минус:
@OptIn(PreviewOnly::class) придётся писать в каждой превью-функции вручную, автоматического opt-in для @Preview нет. Но это копейки по сравнению с тем, что превью-composable физически не попадёт в продакшн.Источник le0nidas.gr
#Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
👍36👎8
This media is not supported in your browser
VIEW IN TELEGRAM
HotSwan - быстрое обновление Composable на реальном устройстве. Доступно как плагин для Android Studio
Я выбрал другой путь - делаю СMP проект с поддержкой Android + Desktop JVM и так можно быстро проверять + делать код чище.
#Compose
Я выбрал другой путь - делаю СMP проект с поддержкой Android + Desktop JVM и так можно быстро проверять + делать код чище.
#Compose
👍16👎10
Самое интересное из нового: поддержка Shared Elements между экранами. Теперь достаточно обернуть
NavDisplay в SharedTransitionLayout и передать scope:SharedTransitionLayout {
NavDisplay(
backStack = backStack,
sharedTransitionScope = this
)
}Второе большое добавление —
SceneDecoratorStrategy. Отдельный интерфейс для декорирования сцен общими UI-элементами или для шаринга состояния между ними. Логика декорирования теперь отделена от логики выбора сцены в SceneStrategy.Type safe metadata DSL через
MetadataKey. Больше не нужны строковые ключи — типы значений описаны статически. Готовые NavMetadataKey позволяют задавать анимации переходов прямо в entryProvider:entry<ScreenC>(
metadata = metadata {
put(NavDisplay.TransitionKey) {
slideInVertically { it } togetherWith fadeOut()
}
}
) { ... }
#compose #navigation3 #jetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
👍58👎3
Что нового:
👉 Визуальная отладка переходов Shared Elements
👉 Переработанная поддержка трекпадов — теперь работают как мышь и распознают жесты
👉 Preview Wrappers для более быстрой работы с превью
👉 Host Defaults для KMP-проектов
👉 Testing APIs v2 для корутин
👉 Экспериментальные API: Styles, MediaQuery, Grid, FlexBox
Подробности по каждому пункту — отдельными постами в @compose_broadcast
#Compose #Android #AndroidJetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16👎2
В Compose 1.11.0 завезли новый интерфейс PreviewWrapper и аннотацию @PreviewWrapperProvider. Идея простая: вместо того чтобы оборачивать каждый Preview в свою тему, CompositionLocalProvider, моки навигации и прочее, ты один раз описываешь обёртку и просто навешиваешь её аннотацией.
Выглядит это так:
class ThemeWrapper : PreviewWrapper {
@Composable
override fun Wrap(content: @Composable () -> Unit) {
JetsnackTheme {
content()
}
}
}@PreviewWrapperProvider(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
Button(onClick = {}) {
Text("Demo")
}
}
Сценарии где может пригодиться:
👉 встроить тему в превью
👉 подложить FakeNavController или LocalActivity
👉 обернуть в Hilt/Koin провайдер с тестовыми зависимостями
👉 прокинуть моки через CompositionLocal
Раньше для этого либо городили собственную функцию и вызывали её руками в каждом превью, либо писали кастомные
@Preview аннотации с ограниченным набором параметров.‼️ ВАЖНО: фича работает только в Android Studio Panda 4 и выше. В более старых версиях аннотация просто проигнорируется.
#compose #jetpackcompose #android
Please open Telegram to view this post
VIEW IN TELEGRAM
👍54👎5
This media is not supported in your browser
VIEW IN TELEGRAM
#Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
👍30👎2
// Пример использования
LookaheadAnimationVisualDebugging(
overlayColor = Color(0x4AE91E63),
isEnabled = true,
multipleMatchesColor = Color.Green,
isShowKeylabelEnabled = false,
unmatchedElementColor = Color.Red,
) {
SharedTransitionLayout {
CompositionLocalProvider(
LocalSharedTransitionScope provides this,
) {
// your content
}
}
}
#Compose
👍13👎5
До недавнего времени стилизация компонентов в Compose делалась через параметры Composable функции (
color = ..., padding = ...) или модификаторы. Это работало, но могло приводить к:👉 избыточным рекомпозициям при смене состояний;
👉 дублированию кода для разных вариаций кнопок/карточек;
👉 сложностям с анимацией переходов между стилями.
Google представил Styles API (экспериментальный, о причинах такого статуса ниже) — новый подход, вдохновлённый CSS. Нужен Jetpack Compose 1.11.0 или свежее
Ключевые возможности
Стили вычисляются на этапах layout и drawing, минуя composition. Это значит, что изменение стиля (например, при наведении) не вызывает рекомпозицию родительских компонентов.
Без кучи
if/else и animate*AsState. Просто описываете стиль для каждого состояния (нажат, сфокусирован, включён, ошибка и т.д.).Переходы между состояниями анимируются автоматически с физическими параметрами (демпфирование, жёсткость). Не нужно писать
Animatable или Transition.// Пример использования стиля
// Определяем стиль для кнопки
val buttonStyle = Style {
default {
backgroundColor = Color.Blue
shape = RoundedCornerShape(8.dp)
}
pressed {
backgroundColor = Color.DarkBlue
scale = 0.98f
}
disabled {
backgroundColor = Color.Gray
alpha = 0.5f
}
}
// Используем
Button(
onClick = { /* ... */ },
style = buttonStyle, // ← вместо кучи параметров
enabled = isEnabled
) {
Text("Нажми меня")
}
style — новый параметр, который появляется у всех компонентов Material 3 и базовых (Box, Row, Column).⚠️ Styles API не заменяет модификаторы
Модификаторы остаются для позиционирования, кликов, размеров. Styles API заменяет только внутреннюю стилизацию (цвета, формы, тени, отступы внутри компонента). Это как разделение «темы» и «вёрстки».
API остаётся экспериментальным пока на него полностью не перейдет Material 3 Compose, чтобы учесть все необходиcмоти API и не делать breaking changes. По работе оно уже стабильно, но вот изменения в коде, возможно, будут.
🔗 Официальная документация
В целом с таким подходом уже привыкли работать в Android XML Layout, то почему бы сразу было его не использовать? Тем более в Compose плюсы очевидны!
#Compose #Material
Please open Telegram to view this post
VIEW IN TELEGRAM
👍85👎3
До сих пор для сеток у нас были только ленивые
LazyVerticalGrid / LazyHorizontalGrid. Но если все элементы уже в памяти (небольшое количество) и нужен точный контроль над расположением ячеек — пригождается новый экспериментальный Grid.// Пример
Grid(config = {
column(100.dp)
column(1.fr) // забирает остаток строки
row(50.dp)
row(80.dp)
gap(8.dp)
}) {
Box(Modifier.gridItem().fillMaxSize()) { ... }
Box(Modifier.gridItem().fillMaxSize()) { ... }
Box(Modifier.gridItem().fillMaxSize()) { ... }
Box(Modifier.gridItem().fillMaxSize()) { ... }
}
Работает на Android и KMP (iOS, Desktop, Web) – общий API
🔗 Документация по Grid
#Compose #KMP #Android #iOS #Desktop #Web #CMP
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32👎2
This media is not supported in your browser
VIEW IN TELEGRAM
В составе
androidx.compose.foundation:layout 1.11.0 появился компонент FlexBox. Компоновка на основе правил CSS Flexbox. Поддерживает перенос элементов (wrap), веса (weight), выравнивание по главной и поперечной осям. Сразу вышел с поддержкой Compose Multiplatform.FlexBox(
modifier =
Modifier.fillMaxWidth(),
config = {
flexDirection = Row
flexWrap = Wrap
justifyContent = SpaceBetween
}
) {
repeat(items.size) { index ->
Text(
text = items[index],
modifier =
Modifier.weight(1f)
)
}
}
🔗 Анонс в блоге Android Developers
🔗 API Reference
#Compose #CMP
Please open Telegram to view this post
VIEW IN TELEGRAM
👍62👎3
В апрельском релизе Jetpack Compose под номером 1.11 в compose-runtime завезли четыре новых API:
HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey и ViewTreeHostDefaultKey. Плюс билдер compositionLocalWithHostDefaultOf для авторов библиотек.Он позволяют объявить
CompositionLocal, у которого дефолтное значение резолвится из окружения хоста — например, через Android View tag'и (как это делает ViewTreeLifecycleOwner или ViewTreeOnBackPressedDispatcherOwner). Раньше для такого паттерна была обязательна зависимость на compose-ui. Теперь только compose-runtime.Раньше чтобы из библиотеки достать значение из View tree, приходилось тянуть compose-ui ради LocalView и платформенные функции поиска по дереву View. Код жил в Android-сорсах, в commonMain такое не положишь:
// androidMain — compose-ui + Android-only API
val LocalMyOwner = compositionLocalOf<MyOwner?> { null }
@Composable
fun ProvideMyOwner(content: @Composable () -> Unit) {
val view = LocalView.current
val owner = remember(view) {
view.findViewTreeMyOwner()
}
CompositionLocalProvider(LocalMyOwner provides owner) {
content()
}
}
С новым API описание CompositionLocal живёт в commonMain и тянет только compose-runtime. Связку с View tree описывает ViewTreeHostDefaultKey, и хост сам отдаёт значение через своего провайдера:
// commonMain — только compose-runtime
val MyOwnerKey = ViewTreeHostDefaultKey<MyOwner>(
viewTagId = R.id.view_tree_my_owner
)
val LocalMyOwner = compositionLocalWithHostDefaultOf(MyOwnerKey)
// Использование — без изменений
@Composable
fun MyComponent() {
val owner = LocalMyOwner.current
// ...
}
Теперь авторы Compose библиотек могут держать определение CompositionLocal в общем модуле без зависимости на compose-ui. Профит - меньше транзитивных зависимостей в KMP-библиотеках и более чистое разделение слоёв runtime и UI.
#Compose #CMP
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21👎5
Главные фичи:
Breaking изменения, которые заденут почти всех:
👉 Минималка Kotlin поднята до 2.3.10
👉 Минимальная iOS теперь 14 (поддержка 13 ушла)
👉 iosX64 и macosX64 удалены полностью
👉 Shader на не-Android стал wrapper-классом
Я ждал нативный input на iOS с того момента, как Compose туда заехал. Текущая реализация на Skia всегда чувствовалась чужой на ощупь, особенно при сложном выделении и системных меню. Надо пробовать!
#compose #cmp #kotlin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26👎4
Forwarded from Android Broadcast
‼️ Android View всё! Да здравствует Compose!
Google официально объявила о переходе к стратегии «Compose-first» и прекращении развития Android View, переводя его в режим поддержки.
Что это значит:
👉 Классы android.widget.* в Android SDK будут находиться в режиме поддержки.
👉 Библиотеки Android Jetpack (включая RecyclerView) также переходят в режим поддержки.
👉 Все инструменты в Android Studio будут создаваться только для Compose.
👉 Документация будет писаться только для Compose, однако некоторые разделы про View останутся.
🔗 Источник - оф сайт Android Developers
#Android #AndroidDev #Compose
Google официально объявила о переходе к стратегии «Compose-first» и прекращении развития Android View, переводя его в режим поддержки.
Что это значит:
👉 Классы android.widget.* в Android SDK будут находиться в режиме поддержки.
👉 Библиотеки Android Jetpack (включая RecyclerView) также переходят в режим поддержки.
👉 Все инструменты в Android Studio будут создаваться только для Compose.
👉 Документация будет писаться только для Compose, однако некоторые разделы про View останутся.
🔗 Источник - оф сайт Android Developers
#Android #AndroidDev #Compose
👍97👎21
Протестировал новый ввод на iOS из Compose 1.11.0. Становится нативнее по поведению, но вот надо проверять на iOS смартфоне тем кто им регулярно пользуется
#Compose #iOS
#Compose #iOS
👍12👎4
Forwarded from Aurora Developers
Представлена альфа-версия 0.0.4 проекта адаптации Compose Multiplatform для ОС Аврора
Проведена глубокая работа над инструментарием, экосистемой и стабильностью фреймворка, чтобы разработчики могли комфортно создавать мобильные приложения для доверенной операционной системы используя привычный инструментарий — язык программирования Kotlin.
Альфа-версия фреймворка Compose Multiplatform опубликована в репозитории mos.hub под открытой лицензией. Каждый желающий имеет возможность внести свой вклад и, тем самым, повлиять на развитие проекта.
Главные изменения в альфа-версии 0.0.4 проекта адаптации Compose Multiplatform для ОС Аврора:
Инструментарий разработчика
• Aurora Build — Gradle-плагин для сборки проектов под ОС Аврора
• Aurora Devices — Gradle-плагин для запуска приложений на устройстве и в эмуляторе
Расширение возможностей фреймворка
• Поддержка системного буфера обмена
• Поддержка ресурсов
• Поддержка локализации приложений
Поддержка новых платформ для разработки
• Добавлена поддержка Windows
• Добавлена поддержка macOS (частичная)
Экосистема и библиотеки
• Новая библиотека для работы с D-bus из Kotlin и поддержка популярных библиотек build-konfig, datetime, kamel, kermit, koin, ktor и sqldelight
Качество и стабильность
• Исправлены проблемы с многопоточностью
• Добавлена поддержка Unit и интеграционного тестирования. Все компоненты экосистемы Kotlin для ОС Аврора получают поддержку многоуровневого тестирования в рамках стабилизации
Референсные приложения
• Опубликовано референсное приложение StudentBox CMP
Новая версия уже доступна для разработчиков.Пробуйте прямо сейчас — все примеры и API в документации.
#АврораОС
@AuroraDevelopers
Проведена глубокая работа над инструментарием, экосистемой и стабильностью фреймворка, чтобы разработчики могли комфортно создавать мобильные приложения для доверенной операционной системы используя привычный инструментарий — язык программирования Kotlin.
Альфа-версия фреймворка Compose Multiplatform опубликована в репозитории mos.hub под открытой лицензией. Каждый желающий имеет возможность внести свой вклад и, тем самым, повлиять на развитие проекта.
Главные изменения в альфа-версии 0.0.4 проекта адаптации Compose Multiplatform для ОС Аврора:
Инструментарий разработчика
• Aurora Build — Gradle-плагин для сборки проектов под ОС Аврора
• Aurora Devices — Gradle-плагин для запуска приложений на устройстве и в эмуляторе
Расширение возможностей фреймворка
• Поддержка системного буфера обмена
• Поддержка ресурсов
• Поддержка локализации приложений
Поддержка новых платформ для разработки
• Добавлена поддержка Windows
• Добавлена поддержка macOS (частичная)
Экосистема и библиотеки
• Новая библиотека для работы с D-bus из Kotlin и поддержка популярных библиотек build-konfig, datetime, kamel, kermit, koin, ktor и sqldelight
Качество и стабильность
• Исправлены проблемы с многопоточностью
• Добавлена поддержка Unit и интеграционного тестирования. Все компоненты экосистемы Kotlin для ОС Аврора получают поддержку многоуровневого тестирования в рамках стабилизации
Референсные приложения
• Опубликовано референсное приложение StudentBox CMP
Новая версия уже доступна для разработчиков.Пробуйте прямо сейчас — все примеры и API в документации.
Хотите помочь проекту стать лучше? Присоединяйтесь к разработке на mos.hub. Мы открыты к вашему коду и экспертизе. Вместе мы сможем сделать инструмент максимально полезным для всего сообщества.
Ссылка на репозиторий
#АврораОС
@AuroraDevelopers
👎57👍18