Освой Compose играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Compose: @Preview

Обновлено 18.04.2024, 19 июня 2025

Аннотация @Preview позволяет задать внешний вид предварительного просмотра создаваемого приложения.

По умолчанию студия предлагает использовать аннотацию только с одним параметром @Preview(showBackground = true). На самом деле параметров гораздо больше. Её исходник выглядит следующим образом.


public constructor Preview(
    val name: String = "",
    val group: String = "",
    @IntRange(from = 1.toLong()) val apiLevel: Int = -1,
    val widthDp: Int = -1,
    val heightDp: Int = -1,
    val locale: String = "",
    @FloatRange(from = 0.01.toDouble()) val fontScale: Float = 1f,
    val showSystemUi: Boolean = false,
    val showBackground: Boolean = false,
    val backgroundColor: Long = 0,
    @UiMode val uiMode: Int = 0,
    @Device val device: String = Devices.DEFAULT,
    @Wallpaper val wallpaper: Int = Wallpapers.NONE
)

Можно обойтись вообще без параметров. Ошибки не будет.


@Preview
@Composable
fun DefaultPreview() {
    Content()
}

name

Если вы обратили внимание, то название у окна предварительного просмотра совпадает с именем функции DefaultPreview(). Вы можете задать своё имя через параметр name.


@Preview (name = "Можно всех кошечек посмотреть?")

По умолчанию элементы выводятся на прозрачный фон, что не всегда удобно. Можно добавить параметр showBackground - впрочем он уже и так у вас был изначально.

backgroundColor

Но фон по умолчанию белый, а вам хочется другой? Хорошо, добавьте ещё один параметр backgroundColor.


@Preview(
    name = "Можно всех кошечек посмотреть?", 
    showBackground = true,
    backgroundColor = 0xCA7971
)

Preview

widthDp/heightDp

Можно задать размеры окна предварительного просмотра через widthDp и heightDp.


@Preview(
    widthDp = 300,
    heightDp = 400
)

group

А ещё можно группировать окна предварительного просмотра для разных компонентов в сложных проектах. Тогда можно будет переключаться между ними через меню или смотреть все элементы вместе.


@Preview(
    name = "Просмотр котов",
    showBackground = true,
    group = "Коты"
)
@Composable
fun DefaultPreview() {
    Text(text = "Привет, киска!")
}

@Preview(
    name = "Cat Preview",
    group = "Cats",
    showBackground = true
)
@Composable
fun SecondPreview() {
    Box {
        Text(text = "Hello Kitty!")
    }
}

Посмотрите два варианта, чтобы понять, как это работает.

Group Preview Group Preview

А можно использовать сразу несколько аннотаций с разным набором параметров, чтобы видеть поведение макета в разных условиях.


@Preview(
    name = "Можно всех кошечек посмотреть?",
    showBackground = true,
    showSystemUi = true
)
@Preview(
    name = "Compact Preview",
    widthDp = 300,
    heightDp = 200
)
@Composable
fun DefaultPreview() {
    Content()
}

A few annotations

showSystemUi

Хочется увидеть, как компоненты будут смотреться на экране телефона? Добавьте параметр showSystemUi.


@Preview(
    name = "Можно всех кошечек посмотреть?",
    showSystemUi = true
)

showSystemUi

device

Можно выбрать конкретный телефон из Pixel/Nexus через параметр device.


@Preview(
    name = "Можно всех кошечек посмотреть?",
    showSystemUi = true,
    device = Devices.NEXUS_6P
)

Другие варианты.


@StringDef(
    open = true,
    value = [
        Devices.DEFAULT,
        Devices.NEXUS_7,
        Devices.NEXUS_7_2013,
        Devices.NEXUS_5,
        Devices.NEXUS_6,
        Devices.NEXUS_9,
        Devices.NEXUS_10,
        Devices.NEXUS_5X,
        Devices.NEXUS_6P,
        Devices.PIXEL_C,
        Devices.PIXEL,
        Devices.PIXEL_XL,
        Devices.PIXEL_2,
        Devices.PIXEL_2_XL,
        Devices.PIXEL_3,
        Devices.PIXEL_3_XL,
        Devices.PIXEL_3A,
        Devices.PIXEL_3A_XL,
        Devices.PIXEL_4,
        Devices.PIXEL_4_XL,
        Devices.AUTOMOTIVE_1024p
    ]
)

uiMode

Рассмотрим параметр uiMode. С его помощью можно, например, установить тёмную тему. Только не забудьте у текста поменять цвет шрифта, иначе будете искать чёрную кошку в чёрной комнате.


@Composable
fun Content() {
    Text(
        text = "Мурзик",
        color = Color.White,
        fontSize = 50.sp
    )
}

@Preview(
    name = "Можно всех кошечек посмотреть?",
    showBackground = true,
    showSystemUi = true,
    uiMode = UI_MODE_NIGHT_YES
)
@Composable
fun DefaultPreview() {
    Content()
}

uiMode

Кроме UI_MODE_NIGHT_YES можно использовать множество других вариантов.


@IntDef(
    value = [
        UI_MODE_TYPE_MASK,
        UI_MODE_TYPE_UNDEFINED,
        UI_MODE_NIGHT_NO,
        UI_MODE_NIGHT_YES,
        UI_MODE_TYPE_APPLIANCE,
        UI_MODE_TYPE_CAR,
        UI_MODE_TYPE_DESK,
        UI_MODE_TYPE_NORMAL,
        UI_MODE_TYPE_TELEVISION,
        UI_MODE_TYPE_VR_HEADSET,
        UI_MODE_TYPE_WATCH,
        UI_MODE_NIGHT_MASK,
        UI_MODE_NIGHT_UNDEFINED,
        UI_MODE_NIGHT_NO,
        UI_MODE_NIGHT_YES
    ]
)

Позже появилась новая аннотация @PreviewLightDark.

locale

Если приложение использует разные локали, например, строковые ресурсы на разных языках, то можно увидеть это на экране. Немного переделаем базовый пример. Также надо подготовить ресурсы в файле res/values-ru/strings.xml


@Composable
fun Greeting(name: String) {
    Text(text = stringResource(id = R.string.hello) + " \$name!")
}

@Preview(showBackground = true, locale = "en")
@Preview(showBackground = true, locale = "ru")
@Composable
fun DefaultPreview() {
    ComposeTheme {
        Greeting(stringResource(id = R.string.barsik))
    }
}

Preview Locale

fontScale

Параметр fontScale позволяет установить масштабирование шрифта от базового значения.


@Preview(fontScale = 2.00f, showBackground = true)
@Composable
fun DefaultPreview() {
    ComposeTheme {
        Greeting(stringResource(id = R.string.barsik))
    }
}

Позже появилась аннотация @PreviewFontScale.

wallpaper

Можно установить динамические обои. Сам пока не использовал на практике.


@Preview(showBackground = true, wallpaper = Wallpapers.BLUE_DOMINATED_EXAMPLE)

LoremIpsum

Если вам нужно протестировать, как будет выглядеть текстовая метка с разным количеством слов, то можно воспользоваться классом LoremIpsum.


@Preview(showBackground = true)
@Composable
fun ContentPreview() {
    YourComposeTheme {
        Text(text = LoremIpsum(words = 4)
            .values
            .toList()
            .first()
            .toString()
        )
    }
}

@PreviewLightDark

Вместо двух аннотаций для светлого и тёмного режимов, можно использовать родственную аннотацию @PreviewLightDark.


// Вместо
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
@Composable
private fun Preview() {
    ...
}


@PreviewLightDark
@Composable
fun Preview(){
    YourComposeTheme {
        Text(text = "Meow")
    }
}

@PreviewFontScale

Если нужно протестировать сразу несколько размеров шрифта, то вместо многочисленных вызовов с параметром fontScale можно использовать аннотацию @PreviewFontScale.


// Вместо
@Preview(name = "85%", fontScale = 0.85f)
@Preview(name = "100%", fontScale = 1.0f)
@Preview(name = "115%", fontScale = 1.15f)
@Preview(name = "130%", fontScale = 1.3f)
@Preview(name = "150%", fontScale = 1.5f)
@Preview(name = "180%", fontScale = 1.8f)
@Preview(name = "200%", fontScale = 2f)
@Composable
private fun Preview() {
    ...
}


@PreviewFontScale
@Composable
fun Preview(){
    YourComposeTheme {
        Text(text = "Meow")
    }
}

@PreviewScreenSizes

Сразу посмотреть на устройствах разных размеров можно через @PreviewScreenSizes.


// Вместо
@Preview(name = "Phone", device = PHONE, showSystemUi = true)
@Preview(name = "Phone - Landscape",
    device = "spec:width = 411dp, height = 891dp, orientation = landscape, dpi = 420",
    showSystemUi = true)
@Preview(name = "Unfolded Foldable", device = FOLDABLE, showSystemUi = true)
@Preview(name = "Tablet", device = TABLET, showSystemUi = true)
@Preview(name = "Desktop", device = DESKTOP, showSystemUi = true)
@Composable
private fun Preview() {
    ...
}

@PreviewScreenSizes
@Composable
fun Preview(){
    YourComposeTheme {
        Text(text = "Meow")
    }
}
Картинки из окна предварительного просмотра можно копировать через контекстное меню Copy Image.

Дополнительное чтение

Реклама