Найти в Дзене

Вынос размеров в ресурсы в Compose Multiplatform + Kotlin Multiplatform

Почему-то не смог найти верной информации на этот счёт. Пришлось прибегнуть к помощи Gemini в Android studio. Для Compose Multiplatform стандартный механизм ресурсов (composeResources) на данный момент напрямую не поддерживает тип <dimen> так, как это делает Android. Создавать файл dimens.xml не нужно.
Рекомендуемый способ выноса размеров в KMP — использование CompositionLocal и специальных объектов с константами. 1. Создайте файл src/commonMain/kotlin/com/test/testproject/presentation/ui/AppDimensions.kt:
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
data class AppDimensions(
val paddingSmall: Dp = 8.dp,
val paddingMedium: Dp = 16.dp,
val paddingStandard: Dp = 40.dp,
val textSizeLarge: TextUnit = 20.sp
)
val LocalDimensions = staticCompositionLocalOf { AppDimensions() } 2. Подключите размеры в тему

Почему-то не смог найти верной информации на этот счёт. Пришлось прибегнуть к помощи Gemini в Android studio.

Для Compose Multiplatform стандартный механизм ресурсов (composeResources) на данный момент напрямую не поддерживает тип <dimen> так, как это делает Android. Создавать файл dimens.xml не нужно.

Рекомендуемый способ выноса размеров в KMP — использование CompositionLocal и специальных объектов с константами.

1. Создайте файл src/commonMain/kotlin/com/test/testproject/presentation/ui/AppDimensions.kt:

import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

data class AppDimensions(
val paddingSmall: Dp = 8.dp,
val paddingMedium: Dp = 16.dp,
val paddingStandard: Dp = 40.dp,
val textSizeLarge: TextUnit = 20.sp
)

val LocalDimensions = staticCompositionLocalOf { AppDimensions() }

2. Подключите размеры в тему.
Обычно это делается в вашей основной функции темы. Если её нет в commonMain, можно обернуть экран в CompositionLocalProvider.

3. Теперь можно использовать размеры во всем приложении:
import com.test.testproject.presentation.ui.LocalDimensions

@Composable
fun LoginScreen() {

// Получаем доступ к размерам
val dimensions = LocalDimensions.current

Scaffold { innerPadding ->
Column(
modifier = Modifier
.padding(innerPadding)
.safeContentPadding()
.imePadding()
.fillMaxSize()
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {

TextField(
state = rememberTextFieldState(""),
// Вместо 40.dp используем dimensions.paddingStandard
modifier = Modifier.padding(horizontal = dimensions.paddingStandard),
label = { Text("Email") },
// ...
)

Почему это лучше, чем XML в Multiplatform:
1. Type Safety: Вы не ошибетесь с типом (Dp или Sp).
2. Производительность: staticCompositionLocalOf работает очень быстро для констант.
3. Гибкость: Вы легко сможете изменить размеры для разных экранов (например, для планшетов), просто подменив значение в LocalDimensions.
4. Поддержка KMP: Это работает на Android, iOS и Desktop без дополнительных библиотек.