Привет всем, руководство Jetpack Compose для начинающих снова обновлено.
Если быть точным, то это первая статья из этой серии. Поскольку последняя статья — это всего лишь пролог, позвольте мне поговорить с вами о том, почему нам нужно изучать Compose. Если у вас все еще есть сомнения, вы можете сначала перейти к предыдущей статье. Джетпак для новичков Учебное пособие по созданию композиций, почему вам следует изучать Compose?
Система знаний Compose очень обширна, поэтому я могу написать множество руководств из этой серии. Конечно, я не эксперт по Compose, на данный момент я еще и новичок. По сути, в этом уроке я делюсь этими учебными записями со всеми, одновременно изучая Compose самостоятельно. Я надеюсь, что каждый сможет учиться со мной с нуля.
Compose — альтернатива для Android Новая декларативная платформа пользовательского интерфейса для View. Поскольку это фреймворк пользовательского интерфейса, в нашей первой статье речь пойдет об основных элементы Знание управления и макетирования.
Мои статьи обычно очень практичны, и я надеюсь, что каждый сможет следовать за мной и начать писать код.
Чтобы использовать Compose для написания интерфейсов пользовательского интерфейса, сначала необходимо представить библиотеки зависимостей, связанные с Compose. Однако существует множество библиотек зависимостей, связанных с Compose, и они могут часто меняться. В конце концов, это все еще очень новая среда пользовательского интерфейса, поэтому здесь я научу вас самому простому способу внедрения библиотек зависимостей Compose.
Откройте Android Studio, создайте новый проект с именем ComposeTest и выберите «Создать пустое действие», как показано ниже:
Таким образом, Android Studio создаст для нас проект со средой разработки Compose, и в него естественным образом будут добавлены все необходимые библиотеки зависимостей, как показано ниже:
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation "androidx.compose.ui:ui:$compose_ui_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
implementation 'androidx.compose.material:material:1.2.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"
}
Далее взгляните на автоматически сгенерированный контент в MainActivity:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeTestTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeTestTheme {
Greeting("Android")
}
}
Автоматически сгенерированный здесь код требует некоторых базовых знаний Compose. Мы должны четко понять эти базовые знания, прежде чем приступить к последующему изучению Compose.
Сначала посмотрите на код функции onCreate, где вызывается функция setContent. Обратите внимание, что это имя очень специфическое, поскольку каждому разработчику Android хорошо знакомо имя другой функции: setContentView. Поэтому, когда мы раньше использовали View для написания интерфейсов, мы вызывали функцию setContentView для установки интерфейса. После использования Compose, поскольку View больше не используется, эта новая функция setContent используется для установки интерфейса.
Функция setContent предоставит область Composable, поэтому мы можем по желанию вызывать функцию Composable при ее закрытии.
Так что же такое составная функция? Проще говоря, если @Composable объявлен над функцией, то это составная функция.
Наблюдая за приведенным выше кодом, вы обнаружите, что функция приветствия является составной функцией.
Обратите внимание, что функцию Composable можно вызывать только в области Composable, поэтому, если вы попытаетесь вызвать функцию Greeting вне закрытия функции setContent, вы обнаружите, что компиляция не удалась.
Кроме того, для всех составных функций существует соглашение, согласно которому первая буква имени функции должна быть заглавной. Это сильно отличается от привычек именования функций в Java, поскольку в именах функций Java обычно используется верблюжий регистр с первой буквой в нижнем регистре.
Но именно из-за этого имена составных функций специально требуют, чтобы первая буква была заглавной, чтобы мы могли быстро судить о том, является ли функция составной, по имени функции более интуитивно. В противном случае нам нужно найти местоположение определения функции. . Проверьте, есть ли у него аннотация @Composable.
Тогда, согласно этому правилу, мы можем знать, что две функции ComposeTestTheme и Surface, вложенные в функцию setContent, являются составными функциями.
Среди них функция ComposeTestTheme автоматически создается для нас Android Studio. Она в основном используется для установки и настройки темы проекта. Эту тему мы можем обсудить в следующей статье.
Функция Surface — это общая функция, представленная в библиотеке материалов. Ее основная функция — позволить приложениям лучше адаптироваться к Material Design, например, контролировать высоту тени, управлять цветом содержимого, обрезать формы и т. д. Поскольку мы все еще новички, на данный момент нет необходимости знать слишком много об этой функции Surface, поэтому я не буду здесь слишком подробно ее объяснять.
Кроме того, вы обнаружите, что Android Studio также сгенерировала для нас функцию DefaultPreview. Это также составная функция, но она имеет на одну аннотацию @Preview больше, чем обычная функция Composable. Эта аннотация указывает, что эта функция используется для быстрого предварительного просмотра стиля пользовательского интерфейса.
Другими словами, пользовательский интерфейс, написанный с помощью функции DefaultPreview, позволяет обеспечить быстрый предварительный просмотр без запуска программы на телефоне. Метод работы — щелкнуть опцию «Разделить» в правом верхнем углу основного интерфейса редактирования Android Studio, а затем скомпилировать проект, как показано на рисунке ниже:
Однако лично я считаю, что эта функция быстрого предварительного просмотра не очень полезна, особенно в первые дни, когда было много ошибок. Поэтому, если ваш проект не очень большой и его компиляция не займет много времени, то я думаю, что лучше запустить его прямо на мобильном телефоне, чтобы увидеть эффект.
Итак, теперь давайте запустим проект на мобильном телефоне и посмотрим:
Это то, чего достигает автоматически созданный по умолчанию код: очень простой Hello Android.
Исходный код был объяснен относительно ясно, давайте начнем изучать некоторые знания об основных элементах управления и макете.
Я считаю, что вы должны знать, что в View есть бесчисленное множество элементов управления, которые мы можем использовать. То же самое делает Compose.
Поэтому, если вы хотите освоить все знания по управлению Compose в одной статье, это явно невозможно.
поэтому,Здесь мы изучим только некоторые распространенные варианты использования основных элементов управления в Compose.,Создан, чтобы помочь каждому быстро начать работу. После начала работы,Для более сложного использования вы можете быстро освоить его, выполнив поиск или спросив ChatGPT.
Текст, несомненно, является наиболее часто используемым элементом управления в Compose. Он в основном используется для отображения фрагмента текста, соответствующего TextView среди представлений.
Фактически, в функции приветствия, которая была автоматически сгенерирована только что, использовался элемент управления «Текст», поэтому мы можем видеть слова Hello Android на интерфейсе.
Использовать текст очень просто. Вам нужно всего лишь указать для него текстовый параметр и передать отображаемый контент.
Измените код в MainActivity следующим образом:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeTestTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
SimpleWidgetColumn()
}
}
}
}
}
@Composable
fun SimpleWidgetColumn() {
Column {
Text(text = "This is Text")
}
}
Как видите, здесь мы определяем составную функцию под названием SimpleWidgetColumn, а затем заменяем на нее функцию Greeting, ранее вызванную в функции Surface. Тогда в конечном интерфейсе будет отображаться содержимое, которое мы написали в функции SimpleWidgetColumn.
Итак, в функции SimpleWidgetColumn мы сначала определяем столбец. Этот столбец будет подробно описан позже. На данный момент вам нужно только знать, что он используется для вертикального отображения столбца контента, а его тип функции — LinearLayout в представлении.
Затем в столбце мы добавили текст и указали, что отображаемый контент — «Это текст» с помощью параметра text.
Теперь запустите программу, и результат будет таким, как показано ниже.
Поздравляем, это первый элемент управления в нашем путешествии по Compose. Вы освоили его самые основные функции.
Однако он может отображать только абзац текста, поэтому функция явно слишком однообразна. Фактически, Text предоставляет очень богатый API, позволяющий нам настраивать отображаемый контент. Тогда наиболее распространенным является изменение цвета и размера текста, что мы можем сделать с помощью следующего кода:
@Composable
fun SimpleWidgetColumn() {
Column {
Text(
text = "This is Text",
color = Color.Blue,
fontSize = 26.sp
)
}
}
Перезапустите код, и результат будет таким, как показано ниже:
Кроме того, Text также может реализовывать множество других функций, одну из которых можно понять, просмотрев список его параметров:
fun Text(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
fontStyle: FontStyle? = null,
fontWeight: FontWeight? = null,
fontFamily: FontFamily? = null,
letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null,
lineHeight: TextUnit = TextUnit.Unspecified,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
) {
...
}
Как я только что сказал, здесь мы говорим только о некоторых распространенных способах использования, которые помогут вам быстро приступить к работе. Более сложные варианты использования ждут вас, чтобы вы могли их изучить самостоятельно.
Кнопка должна быть наиболее часто используемым элементом управления после текста. Я думаю, что все знают, для чего это используется, и без моего представления, поскольку оно имеет то же имя, что и кнопка в представлении.
Разница в том, что в View Button является подклассом TextView, и между ними существует отношение наследования. Таким образом, Button фактически расширяет свою функциональность на основе TextView, делая элемент управления кликабельным.
В Compose нет связи между кнопкой и текстом. Это два отдельных элемента управления, и обычно их необходимо использовать вместе.
Итак, давайте сначала попробуем добавить кнопку. Код выглядит следующим образом:
fun SimpleWidgetColumn() {
Column {
...
Button(onClick = { /*TODO*/ }) {
}
}
}
Запустите программу, и вы увидите результаты, как показано ниже:
Хотя кнопка отображается, на ней нет текста.
И если вы все же проследите за мышлением в View и попытаетесь установить атрибут text для Button, чтобы указать текстовое содержимое, вы обнаружите, что Button в Compose вообще не имеет этого атрибута.
Как я только что сказал, между Button и Text в Compose нет отношений наследования, поэтому он не наследует различные возможности от Text.
Итак, как мы можем указать текстовое содержимое для кнопки? Как я только что упомянул, его можно использовать вместе с Text.
Измените код функции SimpleWidgetColumn следующим образом:
@Composable
fun SimpleWidgetColumn() {
Column {
...
Button(onClick = { /*TODO*/ }) {
Text(
text = "This is Button",
color = Color.White,
fontSize = 26.sp
)
}
}
}
Здесь мы помещаем Text в замыкание Button, чтобы можно было указать отображаемый контент для Button. Конечно, здесь не обязательно использовать Text, здесь можно написать и другие элементы управления.
Теперь перезапустите программу, эффект такой, как показано ниже:
Кроме того, мы заметили, что в списке параметров кнопки есть параметр onClick. Это обязательный параметр. При нажатии кнопки будет выполняться логика, указанная в этом параметре.
Чтобы продемонстрировать эту функцию, давайте позволим всплывающему подсказке Toast при нажатии кнопки.
Измените код функции SimpleWidgetColumn следующим образом:
@Composable
fun SimpleWidgetColumn() {
Column {
...
val context = LocalContext.current
Button(onClick = {
Toast.makeText(context, "This is Toast", Toast.LENGTH_SHORT).show()
}) {
Text(
text = "This is Button",
color = Color.White,
fontSize = 26.sp
)
}
}
}
Обратите внимание: если вы хотите отобразить всплывающее сообщение, вам понадобится параметр Context. Чтобы получить объект Context в функции Composable, вы можете вызвать LocalContext.current, чтобы получить его.
Теперь, когда вы нажмете кнопку, эффект будет таким, как показано ниже:
TextField соответствует EditText в View, который представляет собой поле ввода, поэтому это также очень часто используемый элемент управления.
Однако TextField не так прост в использовании, как EditText. Его конструкция использования полностью соответствует идее декларативного пользовательского интерфейса. В настоящее время мы еще очень мало знаем об этой идее, поэтому вам может показаться, что этот элемент управления на данный момент затруднителен. .
Сначала давайте попробуем добавить TextField в интерфейс. Код выглядит следующим образом:
@Composable
fun SimpleWidgetColumn() {
Column {
...
TextField(value = "", onValueChange = {})
}
}
В списке параметров TextField есть два обязательных параметра: параметр value используется для указания текстового содержимого, отображаемого в текущем поле ввода, а параметр onValueChange используется для отслеживания изменений текстового содержимого в поле ввода.
Теперь запустите программу, эффект такой, как показано ниже:
Как видите, поле ввода появилось.
Пока это относительно просто, но когда вы попытаетесь ввести контент в поле ввода, вы обнаружите, что независимо от того, что вы вводите на клавиатуре, оно не будет отображаться в поле ввода.
Это самое большое отличие от EditText, поскольку EditText должен иметь возможность отображать вводимый вами контент.
Так почему же TextField не может отображать введенный контент? Для этого потребуется обзор идей декларативного программирования пользовательского интерфейса, которые мы упомянули в предыдущей статье. Тем, кто еще не видел, обратитесь к ней. Джетпак для новичков Учебное пособие по созданию композиций, почему вам следует изучать Compose?
Рабочий процесс декларативного пользовательского интерфейса немного похож на обновление веб-страницы. То есть, когда мы описываем элемент управления, мы должны включать его состояние. Затем, когда какое-либо состояние необходимо изменить, просто обновите элементы интерфейса, как при обновлении веб-страницы, и тогда естественное состояние будет обновлено.
Содержимое, отображаемое в TextField, является состоянием, поскольку по мере ввода содержимое, отображаемое в интерфейсе, также необходимо обновлять.
Итак, здесь при вводе содержимого в TextField мы сначала не обновляем страницу. Во-вторых, даже если выполняется операция обновления, после обновления TextField обнаруживается, что содержимое, указанное параметром value, по-прежнему является пустой строкой, поэтому введенное нами содержимое по-прежнему не может отображаться на экране.
Теперь причина проблемы четко объяснена.,Так как же это решить? Для этого требуется помощь компонента State Compose. Но это еще один пункт знаний,Планирую объяснить это в следующей статье,Я не хочу сильно расходиться в этой статье.,На данный момент мы по-прежнему фокусируемся на основных элементах управления и макетах.,Просто пропустите этот вопрос сейчас.
TextField также предоставляет очень богатый API, позволяющий настраивать его. Например, EditText имеет атрибут подсказки, который используется для отображения наводящего на размышления текста в поле ввода, а затем, как только пользователь что-либо вводит, наводящий на размышления текст исчезает. Так как же TextField реализует подобные функции? Код выглядит следующим образом:
@Composable
fun SimpleWidgetColumn() {
Column {
...
TextField(
value = "",
onValueChange = {},
placeholder = {
Text(text = "Type something here")
}
)
}
}
Здесь заполнитель указывается с помощью параметра заполнителя, который на самом деле аналогичен подсказке. Когда пользователь ничего не вводит в поле ввода, содержимое заполнителя отображается. Как только пользователь вводит что-либо, заполнитель исчезает. Основной эффект показан ниже:
Кроме того, вы можете подумать, что цвет фона поля ввода TextField по умолчанию слишком уродлив. Мы можем легко настроить цвет фона поля ввода TextField с помощью следующего кода:
@Composable
fun SimpleWidgetColumn() {
Column {
...
TextField(
value = "",
onValueChange = {},
placeholder = {
Text(text = "Type something here")
},
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.White
)
)
}
}
Этот TextFieldDefaults может поддерживать настройку любого цвета, который вы хотите настроить, а не только цвета фона поля ввода. Для конкретного использования обратитесь к списку его параметров.
Теперь перезапустите программу, эффект такой, как показано ниже:
Image соответствует ImageView в View, который используется для отображения картинок. Нет сомнений, что это еще один распространенный элемент управления, который необходимо освоить.
Хорошей новостью является то, что использовать Image довольно просто, поэтому скоро мы сможем приступить к работе.
Как мы все знаем, изображения в Android обычно бывают двух распространенных форм: одна — это рисуемые ресурсы, а другая — растровые объекты. Изображение обеспечивает поддержку обеих форм изображений.
Во-первых, давайте посмотрим, как загружать изображения в виде доступных для рисования ресурсов. Код выглядит следующим образом:
@Composable
fun SimpleWidgetColumn() {
Column {
...
Image(
painter = painterResource(id = R.drawable.dog),
contentDescription = "A dog image"
)
}
}
В списке параметров изображения есть два обязательных параметра: параметр Painter используется для указания отображаемого ресурса, а параметр contentDescription используется для указания текстового описания этого ресурса.
Это текстовое описание в основном используется в режиме специальных возможностей для помощи в произношении группам с нарушениями зрения. В ImageView также есть функции типов, но они предоставляются только как необязательный атрибут. Когда дело доходит до изображения Compose, оно становится обязательным параметром.
Конечно, если вы просто не хотите указывать contentDescription для изображения, вы также можете напрямую передать значение null.
Теперь запустите программу, эффект такой, как показано ниже:
Как насчет этого? Это очень просто в использовании?
Давайте посмотрим, как загружать изображения в растровом формате:
@Composable
fun SimpleWidgetColumn() {
Column {
...
val bitmap: ImageBitmap = ImageBitmap.imageResource(id = R.drawable.dog)
Image(
bitmap = bitmap,
contentDescription = "A dog image"
)
}
}
Код также очень прост. Здесь мы сначала используем функцию ImageBitmap.imageResource для преобразования рисуемого ресурса в объект ImageBitmap, а затем передаем его в элемент управления Image.
Следует отметить, что Image получает в Compose собственный объект ImageBitmap, а не традиционный объект Bitmap. Если вы хотите передать здесь традиционный объект Bitmap, вам необходимо дополнительно вызвать функцию asImageBitmap для его преобразования, как показано ниже:
@Composable
fun SimpleWidgetColumn(bitmap: Bitmap) {
Column {
...
Image(
bitmap = bitmap.asImageBitmap(),
contentDescription = "A dog image"
)
}
}
До сих пор мы показывали локальные ресурсы изображений. Итак, что же делать, если вы хотите отобразить онлайн-ресурс изображений?
К сожалению, изображение, предоставленное Compose, не имеет такой возможности. Нам нужно использовать стороннюю библиотеку зависимостей. Конечно, у ImageView нет такой возможности, поэтому мы использовали сторонние библиотеки, например Glide.
В настоящее время Google рекомендует использовать сторонние библиотеки загрузки изображений Compose — Coil и Glide. Я знаю, что все почувствуют себя очень дружелюбно, когда увидят Glide, и, возможно, захотят использовать его. Но на самом деле Coil — это новая библиотека загрузки изображений, основанная на разработке сопрограмм. Ее использование более подходит для Kotlin и проще, поэтому я рекомендую использовать эту новую библиотеку.
Чтобы использовать Coil, нам сначала нужно внедрить его в наш проект:
dependencies {
implementation("io.coil-kt:coil-compose:2.4.0")
}
Затем используйте элемент управления AsyncImage, предоставленный Coil, чтобы легко загрузить ресурсы сетевого изображения. Код выглядит следующим образом:
@Composable
fun SimpleWidgetColumn() {
Column {
...
AsyncImage(
model = "https://img-blog.csdnimg.cn/20200401094829557.jpg",
contentDescription = "First line of code"
)
}
}
Перезапустите программу, чтобы увидеть эффект, но перед этим не забудьте объявить сетевые разрешения в файле AndroidManifest.xml.
ProgressIndicator соответствует ProgressBar в представлении.,То есть используется для отображения индикатора выполнения,Это тоже ядро Основные элементы Одно из управления.
Мы все знаем, что в View есть две распространенные формы ProgressBar, а именно круговой ProgressBar и длинный ProgressBar. ProgressIndicator также имеет эти две формы, и соответствующие элементы управления — CircularProgressIndicator и LinearProgressIndicator. Давайте изучим их одну за другой.
Давайте сначала посмотрим на CircularProgressIndicator. Его использование очень просто, как показано ниже:
@Composable
fun SimpleWidgetColumn() {
Column {
...
CircularProgressIndicator()
}
}
Просто разместите элемент управления CircularProgressIndicator, нам даже не нужно указывать какие-либо параметры.
Теперь запустите программу, эффект такой, как показано ниже:
В дополнение к эффекту по умолчанию мы также можем легко настроить стиль индикатора выполнения. Например, мы можем изменить цвет и толщину линии индикатора выполнения с помощью следующего кода:
@Composable
fun SimpleWidgetColumn() {
Column {
...
CircularProgressIndicator(
color = Color.Green,
strokeWidth = 6.dp
)
}
}
Перезапустите программу, эффект такой, как показано ниже:
Далее давайте посмотрим на использование LinearProgressIndicator, которое тоже очень просто:
@Composable
fun SimpleWidgetColumn() {
Column {
...
LinearProgressIndicator()
}
}
Аналогично, нам нужно только разместить элемент управления LinearProgressIndicator, и эффект работы будет таким, как показано ниже:
Как вы можете видеть, теперь отображается горизонтальный индикатор выполнения в горизонтальном направлении.
Тогда вы, должно быть, подумали об этом: мы можем использовать аналогичный метод для настройки стиля LinearProgressIndicator:
@Composable
fun SimpleWidgetColumn() {
Column {
...
LinearProgressIndicator(
color = Color.Blue,
backgroundColor = Color.Gray
)
}
}
Здесь я указываю цвет переднего плана и цвет фона горизонтального индикатора выполнения соответственно. Давайте почувствуем эффект:
На данный момент, я думаю, были представлены наиболее распространенные элементы управления в Compose.
Конечно, элементы управления, связанные с пользовательским интерфейсом, бесконечны, и в будущем появится бесчисленное множество пользовательских элементов управления. Но если у вас есть базовое представление об элементах управления Compose, вы можете быстро освоить больше контента, просматривая информацию при ее использовании.
Далее мы приступаем к изучению базовой планировки.
По сравнению с View, компоновка Compose на самом деле намного проще. В системе View различные раскладки действительно головокружительны и сложны в освоении.
Хотя в Compose также имеется множество макетов, основных макетов всего три: «Столбец», «Строка» и «Ящик». Взгляните на следующую диаграмму:
Столбец позволяет расположить элементы управления вертикально, что мы только что испытали. Ряд — расположение элементов управления по горизонтали. Столбец и строка соответствуют LinearLayout в представлении.
Box соответствует FrameLayout в View. Если объяснить это таким образом, все поймут это легко.
Некоторые друзья могут задаться вопросом: почему в Compose существует только несколько основных макетов? RelativeLayout и ConstraintLayout также часто используются. Разве у Compose нет соответствующего макета?
Это связано с тем, что дизайн и производительность Compose очень хороши. Одних этих основных макетов в принципе достаточно для написания различных сложных интерфейсов пользовательского интерфейса.
На самом деле в Compose есть еще ConstraintLayout, но я не очень рекомендую его использовать. Причина в том, что причина, по которой мы раньше использовали ConstraintLayout в View, заключается главным образом в том, что производительность View резко падает, когда макет слишком глубоко вложен, в то время как ConstraintLayout может использовать один уровень вложенности макета для завершения написания сложного интерфейса. ценность лежит.
В Compose вообще нет этой проблемы. Используя Compose для написания интерфейсов, вы можете вкладывать макеты на любой глубине, совершенно не влияя на производительность.
Именно по этой причине ConstraintLayout в Compose не имеет особого преимущества. Ведь макет, написанный с использованием Column и Row, лучше с точки зрения читабельности.
Итак, давайте начнем учиться один за другим.
Фактически, мы использовали столбец при объяснении основных элементов управления, поскольку все элементы управления размещены в столбце.
Элементы управления в столбце будут расположены вертикально сверху вниз, и эффект будет таким же, как мы только что видели.
Что еще может сказать в таком случае Колонка? На самом деле, Column имеет много настраиваемого контента.
Прежде всего, вы обнаружите, что все элементы управления в столбце в настоящее время выровнены по левому краю. Есть ли способ выровнять их по центру?
Код на самом деле очень прост, как показано ниже:
@Composable
fun SimpleWidgetColumn() {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
...
}
}
Здесь мы добавляем два параметра в столбец.
Параметр модификатора является очень важным компонентом в Compose. Все элементы управления Compose должны полагаться на него. В нашей следующей статье модификатор будет рассмотрен подробно. На данный момент вам нужно только знать, что после вызова функции fillMaxSize() размер столбца может заполнить родительский макет.
Параметр HorizontalAlignment может указать горизонтальное выравнивание субэлементов управления в столбце. CenterHorizontally означает выравнивание по центру. Кроме того, вы также можете выбрать Начало и Конец.
Перезапустите программу, и вы увидите, что все элементы управления теперь центрированы:
Рисунок 19
Тогда некоторые друзья могут сказать: а что, если мне нужно, чтобы каждый элемент управления в столбце имел разное выравнивание? Конечно, нет проблем. Compose обеспечивает очень широкие возможности настройки. Нам нужно только переопределить выравнивание в параметре-модификаторе соответствующего субэлемента управления:
@Composable
fun SimpleWidgetColumn() {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
modifier = Modifier.align(Alignment.End),
text = "This is Text",
color = Color.Blue,
fontSize = 26.sp
)
...
}
}
В этом случае только первый элемент управления «Текст» будет выровнен по правому краю, а остальные элементы управления останутся по центру, как показано на следующем рисунке:
Помимо указания горизонтального выравнивания субэлементов управления, мы также можем указать вертикальное распределение субэлементов управления. Что это значит? Давайте посмотрим на следующий код:
@Composable
fun SimpleWidgetColumn() {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceEvenly
) {
...
}
}
Здесь мы указываем параметр вертикалиArrangement и устанавливаем для него значение SpaceEvenly. SpaceEvenly означает, что каждый субэлемент управления в Столбце поровну делит пространство Столбца в вертикальном направлении.
Это легко понять, если вы запустите его и увидите эффект, как показано на рисунке ниже:
Это может быть полезной функцией для всех, поскольку в LinearLayout нет подобной функции, или LinearLayout требуется помощь параметра макета_веса для достижения того же эффекта.
Однако методы распределения, которые можно указать с помощью параметраverticalArrangement, очень богаты, и LinearLayout довольно сложно выполнить полностью подобную симуляцию. Поскольку можно указать множество методов распространения, я не могу продемонстрировать их все. Итак, давайте посмотрим на официальный пример анимации Google, чтобы быстро понять эффект каждого метода распространения:
Хорошо, это все, что касается Столбца, давайте начнем рассматривать Строку.
После освоения Column довольно просто взглянуть на Row, потому что по сути это одно и то же, только разное по направлению.
Сначала мы просто заменяем Столбец на Строку, не добавляя никаких параметров. Код выглядит следующим образом:
@Composable
fun SimpleWidgetColumn() {
Row {
Text(
text = "This is Text",
color = Color.Blue,
fontSize = 26.sp
)
...
}
}
Запускаем программу, эффект такой, как показано ниже:
Я знаю, что этот эффект уродлив, но это ожидаемо. Поскольку элементы управления в строке действительно расположены горизонтально, но поскольку пространство не может вместить такое количество элементов управления, их можно отображать только вот так.
Но это не мешает нам указывать другие параметры. Например, если мы хотим выровнять эти подэлементы управления по центру в вертикальном направлении, мы можем написать так:
@Composable
fun SimpleWidgetColumn() {
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
) {
...
}
}
Вы обнаружите, что параметры, которые можно указать в столбце и строке, очень разумны.
Поскольку Column представляет собой вертикальный макет, он может указывать только горизонтальное выравнивание, поэтому предоставляется параметр HorizontalAlignment.
В свою очередь, поскольку Row представляет собой горизонтальный макет, он может указывать выравнивание только в вертикальном направлении, поэтому предоставляется параметрverterAlignment.
Теперь перезапустите программу, эффект такой, как показано ниже:
Аналогичным образом, поскольку Column представляет собой вертикальный макет, он может указать метод распределения только в вертикальном направлении, поэтому предоставляется параметрverterArrangement.
Тогда вы, должно быть, догадались, что, поскольку Row представляет собой горизонтальный макет, он может указывать метод распределения только в горизонтальном направлении, поэтому необходимо указать параметр HorizontalArrangement.
На самом деле это правда, но, к сожалению, я не могу продемонстрировать это вам здесь, потому что контент, расположенный в настоящее время горизонтально, превышает отображаемый размер строки. Когда макет больше не может вместить содержимое дополнительных элементов управления, указывать метод его распространения бессмысленно и неэффективно.
Что касается методов распределения, которые можно указать параметром HorizontalArrangement, и их эффектов, я думаю, будет более интуитивно понятно посмотреть непосредственно на эту картину:
Таким образом, мы изучили все функции в строке так же, как и в столбце. Однако, поскольку содержимое строки не может быть отображено, я хотел бы воспользоваться этой возможностью, чтобы поговорить о том, как разрешить пользователям прокручивать содержимое для просмотра содержимого, выходящего за пределы экрана.
Прежде всего, если вы ищете замену RecyclerView или ListView в Compose, то, к сожалению, это не входит в рамки нашей сегодняшней статьи, я напишу специальную статью, чтобы объяснить эту часть.
В ситуации, с которой мы сейчас сталкиваемся, в представлении вы обычно можете вложить слой макета ScrollView в дополнение к содержимому, которое необходимо прокручивать, чтобы содержимое в ScrollView можно было прокручивать.
Compose не требует дополнительной вложенности макета, достаточно использовать только параметр-модификатор. Код выглядит следующим образом:
@Composable
fun SimpleWidgetColumn() {
Row(
modifier = Modifier
.fillMaxSize()
.horizontalScroll(rememberScrollState()),
verticalAlignment = Alignment.CenterVertically,
) {
...
}
}
Здесь мы подключаем функцию горизонтальной прокрутки к параметру-модификатору. Эта функция имеет параметр ScrollState, который является обязательным. Он используется для обеспечения того, чтобы положение прокрутки не терялось при повороте экрана телефона по горизонтали и вертикали. функция RememberScrollState get.
Функции серии Remember — очень важная часть Compose, и я подробно расскажу о них в последующих статьях.
Теперь перезапустите программу, эффект такой, как показано ниже:
Если содержимое столбца не может быть отображено, метод прокрутки столбца аналогичен. Вам нужно только изменить горизонтальную прокрутку на вертикальную прокрутку, которая здесь не будет продемонстрирована.
Box соответствует FrameLayout в представлении. Он не имеет расширенных методов позиционирования. Все элементы управления по умолчанию будут размещены в верхнем левом углу макета. Давайте рассмотрим пример:
@Composable
fun SimpleWidgetColumn() {
Box {
...
}
}
Здесь мы меняем самый внешний макет на Box. Перезапустите программу, эффект такой, как показано ниже:
Как видите, все дочерние элементы управления отображаются в верхнем левом углу макета, а элементы управления, добавленные позже, будут поверх элементов управления, добавленных первыми.
Конечно, в дополнение к этому эффекту по умолчанию, мы также можем указать выравнивание элемента управления в макете, изменив параметр-модификатор подэлемента управления, который аналогичен использованию в столбце.
Измените код функции SimpleWidgetColumn следующим образом:
@Composable
fun SimpleWidgetColumn() {
Box(modifier = Modifier.fillMaxSize()) {
Text(
modifier = Modifier.align(Alignment.TopStart),
...
)
Button(
modifier = Modifier.align(Alignment.TopEnd),
...
})
TextField(
modifier = Modifier.align(Alignment.CenterStart),
...
)
Image(
modifier = Modifier.align(Alignment.CenterEnd),
...
)
CircularProgressIndicator(
modifier = Modifier.align(Alignment.BottomStart),
...
)
LinearProgressIndicator(
modifier = Modifier.align(Alignment.BottomEnd),
...
)
}
}
Сначала мы указываем Modifier.fillMaxSize() для Box, чтобы заполнить его родительским макетом. Затем мы добавляем параметр-модификатор к каждому дочернему элементу управления и указываем их соответствующие выравнивания с помощью Modifier.align, чтобы они не перекрывались.
Теперь перезапустите программу, эффект такой, как показано ниже:
На самом деле, как я только что сказал, ConstraintLayout не так часто используется в Compose. Причина в том, что его самое большое преимущество заключается в том, что однослойный макет, вложенный в Compose, не является преимуществом.
Но не исключено, что некоторым друзьям ConstraintLayout нравится просто потому, что им нравится его способ написания, а не его производительность. Для этих друзей я могу только сказать, что Google полностью учел вас и предоставил версию ConstraintLayout для Compose с аналогичным использованием.
Однако я не буду объяснять эту часть. Если вы являетесь поклонником ConstraintLayout, обратитесь к следующим официальным документам:
https://developer.android.google.cn/jetpack/compose/layouts/constraintlayout
Эта статья почти подошла к концу. Если вы никогда раньше не сталкивались с Compose, то, прочитав эту статью, я думаю, вы сможете написать несколько простых интерфейсов.
Напоследок хочу поделиться с вами еще одним гаджетом. Поскольку в этой статье я говорил о том, чему соответствует определенный элемент управления Compose в View, у некоторых друзей могут возникнуть дополнительные вопросы: чем можно заменить RecyclerView в Compose? Чем можно заменить DrawerLayout в Compose?
Здесь я рекомендую сайт всем:https://www.jetpackcompose.app/What-is-the-equivalent-of-DrawerLayout-in-Jetpack-Compose
Вы можете выбрать компонент в системе просмотра на левой странице этого веб-сайта, а затем на правой странице будет указано, какой компонент ему соответствует в Compose. Это очень практичный веб-сайт для начинающих.
Хорошо, на сегодня это все. Увидимся в следующей оригинальной статье.