안드로이드 공식 문서를 보며 Jetpack Compose
에 대해서 공부해보려고 합니다.
https://developer.android.com/codelabs/jetpack-compose-basics?hl=ko#0
안드로이드 스튜디오를 최신 버전으로 업데이트하니, 프로젝트 생성 시 자동으로 Compose를 사용할 수 있게 설정이 되어 있네요.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeBasicTheme {
// A surface container using the 'background' color from the theme
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() {
ComposeBasicTheme {
Greeting("Android")
}
}
@Composable
이라고 주석으로 이 함수가 UI를 그리는 함수라고 알려줍니다.
그 아래 @Preview
주석은 미리보기 함수입니다.
미리보기는 동일한 파일에 여러개를 만들 수 있습니다.
기존에는 SetContentView
에서 xml 파일을 주어 레이아웃을 정의했지만, Compose를 사용할 때는 Compose 함수를 SetContentView 내부에서 호출하게 됩니다.
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
)
Surface
는 Jetpack Compose에서 UI 구성 요소를 그리는 데 사용하는 함수로, Composable 함수 내부에서 UI 요소를 감싸는 컨테이너 역할을 합니다.
Surface 함수를 사용해서 컨테이너의 색을 변경할 수 있습니다.,
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Surface(
color = MaterialTheme.colorScheme.primary
) {
Text(
text = "Hello $name!",
modifier = modifier,
)
}
}
컨테이너의 색을 다음과 같이 변경할 수 있습니다.
컨테이너의 색이 아닌 텍스트의 색을 변경하려면 어떻게 해야 할까요 ?
텍스트의 Color 속성을 주면 됩니다.
Text(
...
color = Color.Green,
)
크기 변경은 Modifier
속성을 사용하면 됩니다.
Modifier
는 Composable 함수 내에서 사용되며, UI 요소에 적용하여 해당 요소의 모양, 위치, 크기, 스타일 등을 설정하거나 변경할 수 있습니다.
Surface(
modifier = modifier.padding(20.dp),
color = MaterialTheme.colorScheme.primary
) {
Text(
text = "Hello $name!",
modifier = modifier.padding(30.dp),
color = Color.Green,
)
}
위와 같이 modifier
를 통해서 컨테이너와 텍스트의 UI요소를 배치할 수 있습니다.
컴포즈의 장점 중 한가지 인 재사용성 입니다.
다음과 같이 Greeting 함수를 MyApp 내에서 호출함으로써 MyApp은 Greeting을 포함하는 컴포즈로 만들어지고, 이렇게 함으로써 코드의 중복을 피하고 재사용성을 높일 수 있습니다.
이렇게 Composable 함수를 사용하면 각 함수가 독립적으로 수정 가능하며, UI 요소의 재사용과 유지 보수성을 향상시킬 수 있습니다.
...
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeBasicTheme {
MyApp(modifier = Modifier.fillMaxSize())
}
}
}
}
@Composable
private fun MyApp(modifier: Modifier = Modifier) {
Surface(
modifier = modifier,
color = MaterialTheme.colorScheme.background
) {
Greeting("Android")
}
}
...
Column
, Row
, Box
를 사용할 수 있습니다.
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Surface(
color = MaterialTheme.colorScheme.primary
) {
Column(modifier = Modifier.padding(24.dp)) {
Text(
text = "Hello ",
color = Color.Green,
)
Text(
text = "$name!",
color = Color.Green,
)
}
}
}
또한, Compose는 Kotlin의 다른 함수처럼 사용할 수 있습니다.
다음과 같이 for
문을 사용해서 Column에 요소를 추가할 수 있습니다.
@Composable
fun MyApp(
modifier: Modifier = Modifier,
names: List<String> = listOf("World", "Compose")
) {
Column(modifier) {
for (name in names) {
Greeting(name = name)
}
}
}
속성들을 이용해서 아래와 같이 더 깔끔하게 만들 수 있습니다.
@Composable
fun Greeting(name: String) {
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(
vertical = 4.dp, horizontal = 8.dp
)
) {
Column(modifier = Modifier.fillMaxWidth().padding(24.dp)) {
Text(
text = "Hello ",
color = Color.Green,
)
Text(
text = "$name!",
color = Color.Green,
)
}
}
}
버튼은 다음과 같이 추가할 수 있습니다.
Button(
onClick = { } // You'll learn about this callback later
) {
Text("Show less")
}
@Composable
private fun Greeting(name: String) {
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
) {
Row(modifier = Modifier.padding(24.dp)) {
Column(modifier = Modifier.weight(1f)) {
Text(text = "Hello, ")
Text(text = name)
}
ElevatedButton(
onClick = { /* TODO */ }
) {
Text("Show more")
}
}
}
}
컴포저블 내의 변수에 상태를 저장하는 변수를 둘 수 있습니다.
val expanded = remember { mutableStateOf(false) }
이를 활용하여 이전의 버튼에 적용할 수 있습니다.
상태값을 활용해서 버튼을 펼치고, 텍스트를 변경하게 합니다.
@Composable
private fun Greeting(name: String) {
val expanded = remember { mutableStateOf(false) }
val extraPadding = if (expanded.value) 48.dp else 0.dp
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
) {
Row(modifier = Modifier.padding(24.dp)) {
Column(modifier = Modifier
.weight(1f)
.padding(bottom = extraPadding)
) {
Text(text = "Hello, ")
Text(text = name)
}
ElevatedButton(
onClick = { expanded.value = !expanded.value }
) {
Text(if (expanded.value) "Show less" else "Show more")
}
}
}
}