На этой странице представлен общий обзор архитектурных слоев, составляющих Jetpack Compose, а также основные принципы, лежащие в основе этого дизайна.
Jetpack Compose — это не единый монолитный проект; он создается из ряда модулей, которые собираются вместе, образуя полный стек. Понимание различных модулей, составляющих Jetpack Compose, позволит вам:
- Используйте соответствующий уровень абстракции для создания приложения или библиотеки.
- Поймите, когда вы можете «спуститься» на более низкий уровень для большего контроля или настройки.
- Минимизируйте свои зависимости
Слои
Основные уровни Jetpack Compose:
Рисунок 1. Основные уровни Jetpack Compose.
Каждый уровень построен на нижних уровнях, объединяя функциональные возможности для создания компонентов более высокого уровня. Каждый уровень основан на общедоступных API нижних уровней, что позволяет проверять границы модуля и позволяет при необходимости заменить любой уровень. Давайте рассмотрим эти слои снизу вверх.
- Время выполнения
- Этот модуль предоставляет основы среды выполнения Compose, такие как
remember
,mutableStateOf
, аннотацию@Composable
иSideEffect
. Вы можете рассмотреть возможность создания непосредственно на этом уровне, если вам нужны только возможности управления деревом Compose, а не его пользовательский интерфейс. - пользовательский интерфейс
- Уровень пользовательского интерфейса состоит из нескольких модулей (
ui-text
,ui-graphics
,ui-tooling
и т. д.). Эти модули реализуют основы набора инструментов пользовательского интерфейса, такие какLayoutNode
,Modifier
, обработчики ввода, пользовательские макеты и рисование. Вы можете рассмотреть возможность использования этого уровня, если вам нужны только фундаментальные концепции набора инструментов пользовательского интерфейса. - Фундамент
- Этот модуль предоставляет независимые от системы дизайна строительные блоки для пользовательского интерфейса Compose, такие как
Row
иColumn
,LazyColumn
, распознавание определенных жестов и т. д. Вы можете рассмотреть возможность использования базового уровня для создания собственной системы дизайна. - Материал
- Этот модуль обеспечивает реализацию системы Material Design для пользовательского интерфейса Compose, предоставляя систему тем, стилизованные компоненты, индикаторы пульсации, значки. Используйте этот уровень при использовании Material Design в своем приложении.
Принципы проектирования
Руководящим принципом Jetpack Compose является предоставление небольших, сфокусированных частей функциональности, которые можно собрать (или скомпоновать) вместе, а не нескольких монолитных компонентов. Этот подход имеет ряд преимуществ.
Контроль
Компоненты более высокого уровня, как правило, делают больше для вас, но ограничивают объем вашего прямого контроля. Если вам нужно больше контроля, вы можете «спуститься вниз», чтобы использовать компонент более низкого уровня.
Например, если вы хотите анимировать цвет компонента, вы можете использовать API animateColorAsState
:
val color = animateColorAsState(if (condition) Color.Green else Color.Red)
Однако если вам нужно, чтобы компонент всегда начинался серым, вы не сможете сделать это с помощью этого API. Вместо этого вы можете перейти к использованию Animatable
API нижнего уровня:
val color = remember { Animatable(Color.Gray) } LaunchedEffect(condition) { color.animateTo(if (condition) Color.Green else Color.Red) }
API animateColorAsState
более высокого уровня сам по себе построен на API Animatable
более низкого уровня. Использование API нижнего уровня более сложное, но предлагает больше контроля. Выберите уровень абстракции, который лучше всего соответствует вашим потребностям.
Кастомизация
Сборка компонентов более высокого уровня из более мелких строительных блоков значительно упрощает настройку компонентов в случае необходимости. Например, рассмотрим реализацию Button
предоставляемую слоем материала:
@Composable fun Button( // … content: @Composable RowScope.() -> Unit ) { Surface(/* … */) { CompositionLocalProvider(/* … */) { // set LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { Row( // … content = content ) } } } }
Button
собирается из 4-х компонентов:
Материальная
Surface
, обеспечивающая фон, форму, обработку щелчков и т. д.CompositionLocalProvider
, который изменяет альфа-канал содержимого, когда кнопка включена или отключена.ProvideTextStyle
устанавливает стиль текста по умолчанию, который будет использоваться.Row
предоставляет политику макета по умолчанию для содержимого кнопки.
Мы опустили некоторые параметры и комментарии, чтобы сделать структуру более понятной, но весь компонент состоит всего из 40 строк кода, поскольку он просто собирает эти 4 компонента для реализации кнопки. Такие компоненты, как Button
имеют самоуверенность в отношении того, какие параметры они предоставляют, балансируя между возможностью общих настроек и взрывным ростом параметров, которые могут затруднить использование компонента. Например, компоненты материалов предлагают настройки, указанные в системе Material Design, что позволяет легко следовать принципам проектирования материалов.
Однако если вы хотите выполнить настройку, выходящую за рамки параметров компонента, вы можете «спуститься» на уровень и разветвить компонент. Например, Material Design требует, чтобы кнопки имели однотонный фон. Если вам нужен градиентный фон, этот параметр не поддерживается параметрами Button
. В этом случае вы можете использовать реализацию Material Button
в качестве образца и создать свой собственный компонент:
@Composable fun GradientButton( // … background: List<Color>, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Row( // … modifier = modifier .clickable(onClick = {}) .background( Brush.horizontalGradient(background) ) ) { CompositionLocalProvider(/* … */) { // set material LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { content() } } } }
Вышеупомянутая реализация продолжает использовать компоненты из слоя Материала, такие как концепции Материала о текущей альфе контента и текущем текстовом стиле. Однако он заменяет материал Surface
на Row
и стилизует его для достижения желаемого внешнего вида.
Если вы вообще не хотите использовать концепции материалов, например, при создании собственной индивидуальной системы дизайна, вы можете перейти к чистому использованию компонентов базового слоя:
@Composable fun BespokeButton( // … backgroundColor: Color, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Row( // … modifier = modifier .clickable(onClick = {}) .background(backgroundColor) ) { // No Material components used content() } }
Jetpack Compose резервирует самые простые имена для компонентов самого высокого уровня. Например, androidx.compose.material.Text
создан на основе androidx.compose.foundation.text.BasicText
. Это позволяет предоставить вашей собственной реализации наиболее доступное имя, если вы хотите заменить более высокие уровни.
Правильный выбор абстракции
Философия Compose по созданию многоуровневых, повторно используемых компонентов означает, что вам не всегда следует обращаться к строительным блокам нижнего уровня. Многие компоненты более высокого уровня не только предлагают больше функциональности, но и часто реализуют лучшие практики, такие как поддержка специальных возможностей.
Например, если вы хотите добавить поддержку жестов в свой пользовательский компонент, вы можете создать его с нуля, используя Modifier.pointerInput
но на его основе созданы другие компоненты более высокого уровня, которые могут стать лучшей отправной точкой, например Modifier.draggable
, Modifier.scrollable
или Modifier.swipeable
.
Как правило, предпочитают создавать компоненты самого высокого уровня , которые предлагают необходимую вам функциональность, чтобы извлечь выгоду из лучших практик, которые они включают.
Узнать больше
См. пример Jetsnack для примера создания системы индивидуального проектирования.
{% дословно %}Рекомендуется для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Котлин для Jetpack Compose
- Списки и сетки
- Побочные эффекты в Compose