해당 문서는 Modifier를 사용해보았다는 전제 하에 진행됩니다. 만약 Modifier에 어떤 메서드가 있는지 궁금하다면 Android Modifier 공식 문서를 참고해주세요💕
Compose 로 개발하다보면 Modifier 를 자주 만나게 됩니다.
몇 번 써보신 분들은 Modifier
가 아래와 같은 기능들을 제공하는 것을 아실 겁니다.
그렇다면 Modifier
가 뭐길래 저런 기능들이 있을까요?
지금부터, Modifier
에 대해 알아봅시다!
Modifier
란? 유저가 composable에 장식이나 행동을 부여할 수 있도록 해주는 객체입니다. Modifier
를 통해 추가할 수 있는 기능들은 다음과 같습니다.
Modifier
는 composable의 전체적인 구성, 동작과 연결되어 있습니다. 그렇기에 모든 composable에 modifier
매개변수를 허용하고, 최상위 부모 UI 요소에 modifier를 전달하는 것이 좋습니다. 이렇게 하면 코드의 재사용 가능성이 커지며 코드의 동작이 더 예측 가능해지고 이해하기 쉬워집니다.
그렇다면, 위의 Modifier
를 사용할 때 어떠한 점을 유의해야 할까요
Modifier
메서드의 순서에 따라 적용되는 방식이 달라지기 때문에 적용 순서가 매우 중요합니다.
왜 순서가 달라지면 적용 방식이 달라질까요?
상단의 UI Tree를 보면 composable과 Modifier
의 관계를 알 수 있습니다. Modifier
는 Layout Node를 위한 Wrapper Node로 표현됩니다.
여기서 Image
컴포넌트의 Modifier
를 살펴봅시다. composable에 2개 이상의 Modifier
를 추가하면 modifier 체이닝이 생성됩니다. 여러개의 Modifier
를 체이닝하면 각 modifier node는 나머지 chain들과 내부의 layout node을 감쌉니다. Image
컴포넌트에서 clip
과 size
를 체이닝 했을 때, clip Modifier
는 size Modifier
를 감싸고 size Modifier
는 Image layout
을 감싸고 있습니다.
이렇게 각 Modifier
메서드는 이전 함수에서 반환한 Modifier
를 변경하기 때문에 순서는 최종 결과에 영향을 줍니다.
Modifier
순서에 따라 결과가 달라지는 예시로는 다음과 같습니다.
@Composable
fun ArtistCard(/*...*/) {
val padding = 16.dp
Column(
Modifier
.clickable(onClick = onClick)
.padding(padding)
.fillMaxWidth()
) {
// rest of the implementation
}
}
@Composable
fun ArtistCard(/*...*/) {
val padding = 16.dp
Column(
Modifier
.padding(padding)
.clickable(onClick = onClick)
.fillMaxWidth()
) {
// rest of the implementation
}
}
padding
을 먼저 적용하면, padding Modifier
를 감싼 clickable Modifier
가 생성되기 때문에 padding
이 들어간 채 클릭 이벤트가 적용됩니다. 그러나 clickable
을 먼저 적용하면, clickable Modifier
가 생성된 이후에 padding Modifier
가 적용되기 때문에 padding
은 클릭 이벤트가 적용되지 않습니다.
컴포넌트 전체에 적용되는 Modifier
를 파라미터로 받을 때, 파라미터 이름을 modifier
라고 네이밍을 해야 합니다. 또한 default value로 Modifier
를 할당해야 합니다.
만약 기본 Modifier
가 아닌, 특정 메서드를 적용한 Modifier
를 기본으로 두고 싶다면, modifier 매개변수에 특정 메서드를 추가해야 합니다.
여기서 퀴즈!
ProductListItem(
product = item,
onClick = onItemClick,
modifier = Modifier.width(10.dp)
)
@Composable
fun ProductListItem(
product: Product,
onClick: (Product) -> Unit,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.fillMaxSize()
.clickable {
onClick(product)
},
) {
// rest of the implementation
}
}
Column
에는 width(10.dp)
가 적용될까요, fillMaxSize()
가 적용될까요?
정답은 width(10.dp)
입니다!
그렇기 때문에 modifier
에 메서드를 적용하라고 한 겁니다~
만약 전체 컴포넌트가 아닌, 특정 서브 컴포넌트에 modifier를 적용하고 싶다면, 네이밍을 modifier
가 아닌 xxModifier
라고 지어야 합니다.
예를 들어서 Button
에만 modifier
를 지정하고 싶다면, buttonModifier
라고 네이밍을 해야 합니다.
import androidx.compose.foundation.layout.Row
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun ButtonBar(
onOk: () -> Unit,
onCancel: () -> Unit,
modifier: Modifier = Modifier,
buttonModifier: Modifier = Modifier
) {
Row(modifier) {
Button(onCancel, buttonModifier) { Text("Cancel") }
Button(onOk, buttonModifier) { Text("Ok") }
}
}
Modifier | API reference | Android Developers
Constraints and modifier order | Jetpack Compose | Android Developers
API Guidelines for Jetpack Compose