Предварительный просмотр интерфейса с помощью составных макетов

Composable-функция определяется функцией и аннотируется с помощью @Composable:

@Composable
fun SimpleComposable() {
    Text("Hello World")
}

Простой текстовый элемент, содержащий слова "Hello World"

Чтобы включить предварительный просмотр этой composable-функции, создайте другую composable-функцию с аннотациями @Composable и @Preview. Эта новая аннотированная composable-функция теперь содержит composable-функцию, которую вы создали изначально, SimpleComposable:

@Preview
@Composable
fun SimpleComposablePreview() {
    SimpleComposable()
}

Аннотация @Preview сообщает Android Studio, что эта composable-функция должна быть показана в режиме дизайна этого файла. Вы можете видеть обновления в реальном времени в предварительном просмотре composable-функции по мере внесения изменений.

GIF-изображение, на котором показано, как работает предварительный просмотр в Compose.

Вы можете вручную добавить параметры в код, чтобы настроить отрисовку @Preview в Android Studio. Вы даже можете добавить аннотацию @Preview к одной и той же функции несколько раз, чтобы посмотреть, как composable-функция будет выглядеть с разными свойствами.

Одно из основных преимуществ использования composable-функций @Preview – отсутствие необходимости в эмуляторе Android Studio. Вы можете сохранить ресурсоемкий запуск эмулятора для более окончательных изменений внешнего вида и использовать возможность @Preview легко вносить и тестировать небольшие изменения кода.

Чтобы использовать аннотацию @Preview наиболее эффективно, определите экраны с точки зрения состояния, которое они получают на входе, и событий, которые они выводят.

Определите @Preview

В Android Studio есть функции, расширяющие возможности предварительного просмотра composable-функций. Вы можете изменить дизайн контейнера, взаимодействовать с ними или развернуть их непосредственно в эмуляторе или на устройстве.

Размеры

По умолчанию размеры @Preview выбираются автоматически в соответствии с контентом. Чтобы задать размеры вручную, добавьте параметры heightDp и widthDp. Эти значения уже интерпретируются как dp, поэтому добавлять к ним .dp не нужно:

@Preview(widthDp = 50, heightDp = 50)
@Composable
fun SquareComposablePreview() {
    Box(Modifier.background(Color.Yellow)) {
        Text("Hello World")
    }
}

Желтый квадрат с надписью "Hello World"

Предварительный просмотр динамической цветовой темы

Если в вашем приложении включены динамические цвета, используйте атрибут wallpaper, чтобы переключать обои и проверять, как интерфейс реагирует на разные обои, выбранные пользователями. Выберите одну из тем обоев, предлагаемых классом Wallpaper. Для этой функции требуется Compose 1.4.0 или более поздней версии.

Использование на разных устройствах

В Android Studio Flamingo вы можете изменить параметр device аннотации Preview, чтобы задать конфигурации для composable-функций на разных устройствах.

Пример composable-функции

Если параметр device содержит пустую строку (@Preview(device = "")), вы можете вызвать автозаполнение, нажав Ctrl + Space. Затем вы можете установить значения каждого параметра.

Редактирование примера функции

В списке автозаполнения выберите нужный вариант, например @Preview(device = "id:pixel_4"). Вы также можете добавить собственное устройство, нажав spec:width=px,height=px,dpi=int… и задав значения для каждого параметра.

Список
характеристик

Чтобы применить изменения, нажмите Enter, а чтобы отменить – Esc.

Если вы укажете недопустимое значение, объявление будет подчеркнуто красным и может быть доступно исправление (Alt + Enter (⌥ + ⏎ в macOS) > Заменить на…). Инструмент проверки попытается предложить исправление, наиболее близкое к вашему вводу.

Пример недопустимого значения

Региональные настройки

Чтобы протестировать разные региональные настройки, добавьте параметр locale:

@Preview(locale = "fr-rFR")
@Composable
fun DifferentLocaleComposablePreview() {
    Text(text = stringResource(R.string.greeting))
}

Простой текстовый элемент, содержащий слово "Bonjour" и флаг Франции.

Выбрать цвет фона

По умолчанию composable-функция отображается с прозрачным фоном. Чтобы добавить фон, используйте параметры showBackground и backgroundColor. Обратите внимание, что backgroundColor – это Long ARGB, а не значение Color:

@Preview(showBackground = true, backgroundColor = 0xFF00FF00)
@Composable
fun WithGreenBackground() {
    Text("Hello World")
}

Зеленый прямоугольник с надписью "Hello World".

Интерфейс системы

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

@Preview(showSystemUi = true)
@Composable
fun DecoratedComposablePreview() {
    Text("Hello World")
}

Окно предварительного просмотра, в котором показано действие со строкой состояния и панелью действий.

Режим интерфейса

Параметр uiMode может принимать любую из констант Configuration.UI_* и позволяет соответствующим образом изменять поведение предварительного просмотра. Например, вы можете включить ночной режим, чтобы посмотреть, как будет выглядеть тема.

Интерфейс предварительного просмотра

LocalInspectionMode

Вы можете прочитать значение LocalInspectionMode CompositionLocal, чтобы узнать, отображается ли composable-функция в предварительной версии (внутри проверяемого компонента). Если композиция отображается в режиме предварительного просмотра, LocalInspectionMode.current принимает значение true. Эта информация позволяет настроить предварительный просмотр. Например, вы можете показать изображение-плейсхолдер в окне предварительного просмотра вместо реальных данных.

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

@Composable
fun GreetingScreen(name: String) {
    if (LocalInspectionMode.current) {
        // Show this text in a preview window:
        Text("Hello preview user!")
    } else {
        // Show this text in the app:
        Text("Hello $name!")
    }
}

Взаимодействие с @Preview

Android Studio предоставляет функции, позволяющие взаимодействовать с определенными вами предварительными версиями. Это взаимодействие поможет вам понять поведение предварительного просмотра во время выполнения и позволит лучше ориентироваться в пользовательском интерфейсе с помощью предварительного просмотра.

Интерактивный режим

Интерактивный режим позволяет взаимодействовать с предварительным просмотром так же, как и на устройстве, на котором запущена ваша программа, например на телефоне или планшете. Интерактивный режим изолирован в среде песочницы (то есть изолирован от других предварительных просмотров), где вы можете нажимать на элементы и вводить пользовательские данные в предварительном просмотре. Это быстрый способ протестировать разные состояния, жесты и даже анимации composable-функции.

Пользователь нажимает кнопку "Интерактивный" в окне предварительного просмотра.

Видео, на котором пользователь взаимодействует с предварительной версией.

Навигация по коду и структура composable-функций

Наведите указатель на предварительный просмотр, чтобы увидеть контуры содержащихся в нем composable-функций. Если нажать на контур composable-функции, в редакторе откроется ее определение.

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

Запустить предварительный просмотр

Вы можете запустить определенный @Preview на эмуляторе или физическом устройстве. Предварительная версия развертывается в том же проекте, что и новая Activity, поэтому у них одинаковый контекст и разрешения. Вам не нужно писать шаблонный код, запрашивающий разрешение, если оно уже предоставлено.

Нажмите на значок Запустить предварительный просмотр Значок "Запустить просмотр" рядом с аннотацией @Preview или в верхней части окна предварительного просмотра, и Android Studio развернет этот элемент @Preview на подключенном устройстве или эмуляторе.

Пользователь нажимает на предварительный просмотр

Видео, на котором пользователь развертывает предварительную версию на устройстве.

Копировать отрисовку @Preview

Любой предварительный просмотр можно скопировать как изображение, нажав на него правой кнопкой мыши.

Пользователь нажимает на предварительный просмотр, чтобы скопировать его как изображение.

Несколько предварительных просмотров одной и той же аннотации @Preview

Вы можете показать несколько версий одной и той же composable-функции @Preview с разными спецификациями или параметрами. Это позволяет сократить объем шаблонного кода, который вам пришлось бы писать в противном случае.

Шаблоны для нескольких предварительных просмотров

В androidx.compose.ui:ui-tooling-preview 1.6.0-alpha01+ появились шаблоны API Multipreview: @PreviewScreenSizes, @PreviewFontScales, @PreviewLightDark и @PreviewDynamicColors. С их помощью можно одной аннотацией запустить предпросмотр интерфейса Compose в распространенных сценариях.

Предварительный просмотр различных шрифтов и размеров экрана с помощью шаблонов

Как создать аннотации для нескольких предварительных просмотров

С помощью multipreview вы можете определить класс аннотации, который сам по себе имеет несколько аннотаций @Preview с разными конфигурациями. Добавление этой аннотации к composable-функции автоматически отрисовывает все различные предварительные просмотры одновременно. Например, с помощью этой аннотации можно одновременно просматривать несколько устройств, размеров шрифта или тем, не повторяя эти определения для каждой отдельной composable-функции.

Для начала создайте собственный класс аннотаций:

@Preview(
    name = "small font",
    group = "font scales",
    fontScale = 0.5f
)
@Preview(
    name = "large font",
    group = "font scales",
    fontScale = 1.5f
)
annotation class FontScalePreviews

Вы можете использовать эту пользовательскую аннотацию для предварительного просмотра составных элементов:

@FontScalePreviews
@Composable
fun HelloWorldPreview() {
    Text("Hello World")
}

Вкладка Design в Android Studio, на которой показана composable-функция с мелким и крупным шрифтом.

Вы можете комбинировать несколько аннотаций Multipreview и обычных аннотаций Preview, чтобы создать более полный набор предварительных просмотров. Объединение аннотаций для нескольких предварительных просмотров не означает, что будут показаны все возможные комбинации. Вместо этого каждая аннотация Multipreview действует независимо и отображает только свои варианты.

@Preview(
    name = "Spanish",
    group = "locale",
    locale = "es"
)
@FontScalePreviews
annotation class CombinedPreviews

@CombinedPreviews
@Composable
fun HelloWorldPreview2() {
    MaterialTheme { Surface { Text(stringResource(R.string.hello_world)) } }
}

Вкладка Design в Android Studio, на которой показана composable-функция во всех конфигурациях

Возможность комбинировать и сопоставлять элементы в режиме множественного предпросмотра и обычного предпросмотра позволяет более комплексно тестировать многие свойства крупномасштабных проектов.

@Preview и большие наборы данных

Очень часто возникает необходимость передать большой набор данных в предварительный просмотр composable-функции. Для этого просто передайте выборку данных в функцию Composable Preview, добавив параметр с аннотацией @PreviewParameter.

@Preview
@Composable
fun UserProfilePreview(
    @PreviewParameter(UserPreviewParameterProvider::class) user: User
) {
    UserProfile(user)
}

Чтобы предоставить выборку данных, создайте класс, который реализует PreviewParameterProvider и возвращает выборку данных в виде последовательности.

class UserPreviewParameterProvider : PreviewParameterProvider<User> {
    override val values = sequenceOf(
        User("Elise"),
        User("Frank"),
        User("Julia")
    )
}

В результате для каждого элемента данных в последовательности будет создан один предварительный просмотр:

Предварительный просмотр composable-функций Elise, Frank и Julia

Вы можете использовать один и тот же класс поставщика для нескольких предварительных просмотров. При необходимости ограничьте количество предварительных версий, задав параметр limit.

@Preview
@Composable
fun UserProfilePreview2(
    @PreviewParameter(UserPreviewParameterProvider::class, limit = 2) user: User
) {
    UserProfile(user)
}

По умолчанию предварительные версии, использующие @PreviewParameter, называются по индексу параметра и названию свойства (user 0, user 1, user 2 и т. д.), поэтому их сложно различать. Чтобы сделать предварительный просмотр более понятным, вы можете указать собственные отображаемые названия для каждого предварительного просмотра, переопределив getDisplayName() в PreviewParameterProvider. Это помогает различать разные варианты данных или состояния пользовательского интерфейса. Например, вы можете пометить предварительные версии на основе входных данных:

class UserAgePreviewParameterProvider : PreviewParameterProvider<User> {
    // Using a List internally for efficient index-based access
    private val userList = listOf(
        User(name = "Elise", age = 30),
        User(name = "Frank", age = 31),
        User(name = "Julia", age = 40)
    )

    override val values = userList.asSequence()

    override fun getDisplayName(index: Int): String? {
        // Return null or an empty string to use the default index-based name
        val user = userList.getOrNull(index) ?: return null
        return "${user.name} - ${user.age}"
    }
}

Предварительный просмотр с настраиваемыми отображаемыми названиями, показывающими composable-функции Elise – 30, Frank – 31 и Julia – 40

Генерация предпросмотра с помощью ИИ

ИИ-агент в Android Studio может автоматически генерировать предварительные версии Compose для ваших composable-функций. Нажмите правой кнопкой мыши на composable-функцию и выберите AI > Generate Preview for [Composable name] (ИИ > Сгенерировать предпросмотр для [название composable-функции]). Агент анализирует composable-функцию и генерирует шаблонный код @Preview с правильными параметрами, чтобы вы могли быстро проверить, правильно ли отображается интерфейс.

Создайте предварительный просмотр Compose с помощью ИИ.

Класс аннотации @Preview

Вы всегда можете нажать Ctrl или ⌘ и кликнуть по аннотации @Preview в Android Studio, чтобы посмотреть полный список параметров, которые можно настроить для предварительного просмотра.

annotation class Preview(
    val name: String = "",
    val group: String = "",
    @IntRange(from = 1) val apiLevel: Int = -1,
    val widthDp: Int = -1,
    val heightDp: Int = -1,
    val locale: String = "",
    @FloatRange(from = 0.01) 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,
)

Ограничения и рекомендации

Android Studio выполняет код предварительного просмотра непосредственно в области предварительного просмотра. Для этого не требуется запускать эмулятор или физическое устройство, поскольку используется перенесенная часть фреймворка Android под названием Layoutlib. Layoutlib – это специальная версия фреймворка Android, предназначенная для работы вне устройств Android. Цель библиотеки – обеспечить предварительный просмотр макета в Android Studio, который очень близок к его отображению на устройствах.

Ограничения предварительного просмотра

Поскольку предварительный просмотр отображается в Android Studio, он не требует много ресурсов и не использует весь фреймворк Android. Однако при этом действуют следующие ограничения:

  • Нет доступа к сети
  • Нет доступа к файлам
  • Некоторые API Context могут быть доступны не полностью.

Предварительные версии и ViewModels

При использовании ViewModel в composable-функции возможности предварительного просмотра ограничены. Система предварительного просмотра не может создать все параметры, передаваемые в ViewModel, например хранилища, варианты использования, менеджеры и т. д. Кроме того, если ваш ViewModel участвует во внедрении зависимостей (например, с помощью Hilt), система предварительного просмотра не сможет построить весь граф зависимостей для создания ViewModel.

При попытке предварительного просмотра composable-функции с ViewModel Android Studio показывает ошибку при отрисовке этой функции:

Панель проблем в Android Studio с сообщением &quot;Не удалось создать экземпляр ViewModel&quot;

Если вы хотите посмотреть composable-функцию, которая использует ViewModel, создайте другую composable-функцию с параметрами из ViewModel, переданными в качестве аргументов. Таким образом, вам не нужно предварительно просматривать composable-функцию, которая использует ViewModel.

@Composable
fun AuthorScreen(viewModel: AuthorViewModel = viewModel()) {
  AuthorScreen(
    name = viewModel.authorName,
    // ViewModel sends the network requests and makes posts available as a state
    posts = viewModel.posts
  )
}

@Composable
fun AuthorScreen(
  name: NameLabel,
  posts: PostsList
) {
  // ...
}

@Preview
@Composable
fun AuthorScreenPreview(
  // You can use some sample data to preview your composable without the need to construct the ViewModel
  name: String = sampleAuthor.name,
  posts: List<Post> = samplePosts[sampleAuthor]
) {
  AuthorScreen(
      name = NameLabel(name),
      posts = PostsList(posts)
  )
}

Дополнительные ресурсы