При создании проекта, который использует Jetpack Compose, в Android Studio, в проект по умолчанию добавляется файл MainActivity.kt, который содержит одноименный класс MainActivity. Этот класс определяет интерфейс, который мы видим на устройстве/эмуляторе при запуске проекта. Так, по умолчанию графический интерфейс будет выглядеть будет следующим образом:
Рассмотрим основные моменты кода, который добавляется в файл MainActivity.kt и который определяет подобный интерфейс:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import com.example.helloapp.ui.theme.HelloAppTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { HelloAppTheme { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { Greeting("Android") } } } } } @Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Text( text = "Hello $name!", modifier = modifier ) } @Preview(showBackground = true) @Composable fun GreetingPreview() { HelloAppTheme { Greeting("Android") } }
Рассмотрим основные моменты этого кода вкратце. Вначале идет определение пакета, к которому принадлежит класс MainActivity. В моем случае это
пакет com.example.helloapp
:
package com.example.helloapp
Далее идут подключаемые пакеты, функционал который использует класс MainActivity:
import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import com.example.helloapp.ui.theme.HelloAppTheme
Обратите внимание на последний подключаемый пакет - он представляет функционал из каталога ui.theme, который также добавляется в проект по умолчанию и который содержит ряд файлов на языке Kotlin: Color.kt, Theme.kt и Type.kt.
Далее идет определение класса MainActivity
class MainActivity : ComponentActivity() {
ПРиложение на Android определяется как набор объектов, которые называются activity. Объект activity фактически представляет отдельное окно графического приложения. И класс MainActivity как раз представляет окно, которое отображается при запуске приложения
MainActivity наследуется от встроенного класса ComponentActivity. ComponentActivity обеспечивает построение интерфейса из визуальных компонентов и для этого предоставляет минимальный функционал. В частности, ComponentActivity предоставляет метод onCreate(), который вызывается при запуске MainActivity и создает ее интерфейс:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ......
В метод передается объект Bundle, который хранит состояние MainActivity - некоторые значения, которые хранят связанные с MainActivity данные. А в самом методе onCreate()
вначале вызывается реализация этого метода из базового класса ComponentActivity.
Для собственно создания интерфейса в onCreate()
вызывается другой метод базового класса ComponentActivity - метод setContent(). Этот метод
собственно и определяет, какой интерфейс мы увидим на экране устройства. Этот метод выполняет функцию, в которой устанавливается компонент @Composable:
setContent { HelloAppTheme { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { Greeting("Android") } } }
Что такое компонент @Composable? Функция @Composable представляет центральную концепцию
фреймворка Jetpack Compose и, грубо говоря, представляет некоторый визуальный компонент. Причем этот компонент должен быть оформлен в виде функции
с аннотацией @Composable. Так, в проекте по умолчанию пользовательский интерфейс определяется функцией HelloAppTheme
,
которая определена в проекте в файле Theme.kt:
@Composable fun HelloAppTheme( darkTheme: Boolean = isSystemInDarkTheme(), dynamicColor: Boolean = true, content: @Composable () -> Unit ) { ....................................... MaterialTheme( colorScheme = colorScheme, typography = Typography, content = content ) }
Эта функция кроме того, что задает визуальный интерфейс, также обеспечивает соответствие приложения текущей теме (светлой или темной) устройства. Для этого она в качестве первого параметра принимает в качестве первого параметра булевое значение, которое указывает, выбрана ли темная тема. В зависимости от значения этого параметра устанавливает соответствующие цвета, которые определены в файле Color.kt. Последний параметр представляет еще один компонент @Composable - то есть опять же некоторый визуальный компонент. Далее этот компонент передает в в MaterialTheme.
MaterialTheme задает визуальный интерфейс в стиле Material Design. Для этого он использует также настройки шрифта в
виде компонента Typography
из файла Type.kt. Можно сказать, что фактически за компонентом HelloAppTheme
прячется объект MaterialTheme
, которой устанавливает дизайн в стиле
Material Design. Однако что именно передается в сам MaterialTheme
?
Если мы вернемся к файлу MainActivity.kt, то увидим что это компонент Surface:
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { Greeting("Android") }
Surface фактически представляет промежуточный компонент, который задает дополнительное оформление в стиле Material Design. В этот компонент передается компонент Greeting, который определен в том же файле:
@Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Text( text = "Hello $name!", modifier = modifier ) }
Этот компонент использует другой встроенный компонент - Text, который представляет некоторый текст. Именно этот текст в итоге мы увидим на экране устройства.
И в данном случае мы видим, что для вывода простой надписи "Hello Android" используется целый набор компонентов @Composable,
которые вложены в друг друга по принципу матрешки: Text -> Greeting -> Surface -> MaterialTheme -> HelloAppTheme
Однако выше не была упомянута еще одна часть кода MainActivity.kt - функция GreetingPreview
:
@Preview(showBackground = true) @Composable fun GreetingPreview() { HelloAppTheme { Greeting("Android") } }
Здесь мы видим, что GreetingPreview
- это также аннотацию @Composable, и соответственно может представлять некоторую часть визуального интерфейса.
И в реальности он скрывает компонент HelloAppTheme
- то есть фактически весь тот же самый интерфейс, что и определен в классе MainActivity.
Но важная часть определения этого компонента - аннотация @Preview. Она указывает, что данный компонент будет применяться
для предварительного просмотра. То есть, чтобы узнать, как будет выглядеть наш интерфейс, нам необязательно запускать приложение на устройстве/эмуляторе.
В случае небольших, но частых изменений это может быть довольно утомительно. А с помощью этого компонента мы можем увидить, что это будет за интерфейс.
Весь интерфейс в компоненте GreetingPreview
можно увидеть в Android Studio при просмотре в режиме Design или
Split:
С помощью параметров аннотации @Preview можно настраивать предварительный просмотр. Например, если надо отобразить остальную часть экрана, то можно установить
опцию showSystemUi = true
:
@Preview(showSystemUi = true)
Стоит отметить, что окно предварительного просмотра автоматически подхватывает все изменения в интерфейсе приложения
По умолчанию корневым компонентом является HelloAppTheme
, который определен в проекте в файле ui.theme/Theme.kt
.
Однако нам в принципе необязательно использовать всю эту комплексную композицию компонентов. Так, в примере выше, если убрать настройку темы приложения,
то по сути все, что оно делает - это выводит некоторый текст на экран устройства. И в реальности мы могли бы в этом случае ограничиться одним компонентом
Text. Так, изменим код MainActivity.kt следующим образом:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.Text import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Text(text = "Hello METANIT.COM!", fontSize = 28.sp) } } }
Компонент, который представляет по сути то, что мы увидим на экране устройства, передается в метод setContent() класса MainActivity. И в данном случае в этот метод сразу передается компонент Text.
У этого компонента устанавливаются в данном случае два свойства. Свойство text представляет выводимый текст. Кроме того, здесь устанавливается свойство fontSize, которое задает размер шрифта. В качестве значения оно принимает числовое значение в единицах sp.
В итоге приложение будет выглядеть следующим образом: