[Jetpack Compose] Modifier

단디·2024년 7월 17일

Compose

목록 보기
5/12
post-thumbnail

Modifier는 컴포즈 내장 객체로, 컴포저블에 적용될 수 있는 설정을 저장합니다. Modifier 객체는 다양한 메서드를 제공하기 때문에 테두리, 패딩, 배경, 크기, 이벤트 핸들러, 제스처 등 다양한 프로퍼티를 설정할 수 있습니다. Modifier의 인스턴스를 생성하고 프로퍼티들을 설정한 뒤 다른 컴포저블에 전달해서 형태나 행동을 변경할 수 있습니다.

인스턴스 생성하기

val modifier = Modifier

Modifier 키워드를 사용해서 빈 Modifier 인스턴스를 생성할 수 있습니다.

여러 설정 적용하기

val modifier = Modifier
		.padding(all = 16.dp)
		.background(color = Color.Black)

Modifier 인스턴스에 여러 Modifier 확장함수를 연쇄적으로 호출해서 여러 설정을 적용할 수 있습니다.

@Stable
fun Modifier.size(size: Dp) = this.then(
		SizeElement(
		    ...
    )
)
infix fun then(other: Modifier): Modifier =
		if (other === Modifier) this else CombinedModifier(this, other)

확장함수를 연쇄적으로 호출해서 여러 설정이 가능한 이유는 Modifier의 확장함수는 then 확장함수를 사용해서

현재 Modifier 뒤에 다른 Modifier를 순서대로 연결하여 Modifier를 반환하기 때문입니다.

이렇게 만들어진 Modifier는 모든 컴포저블 함수에 modifier의 인자로 전달하여 사용할 수 있습니다.

@Preview(showBackground = true)
@Composable
fun PreviewStudyModifier() {
		StudyModifier(
				modifier = Modifier
						.padding(all = 16.dp)
						.background(color = Color.Blue)
		)
}

@Composable
fun StudyModifier(modifier: Modifier = Modifier) {
		Text(
				modifier = modifier,
				text = "Compose Modifier",
				fontSize = 30.sp
		)
}

Modifier에 padding을 16dp로 지정한 뒤 배경 색상을 Blue로 설정했습니다.

Modifier 연결 순서

modifier-first

위 코드의 실행 결과는 위와 같습니다.

코드를 살짝 바꾸어보겠습니다.

@Preview(showBackground = true)
@Composable
fun PreviewStudyModifier() {
		StudyModifier(
				modifier = Modifier
						.background(color = Color.Blue)
						.padding(all = 16.dp)
		)
}

modifier-first

변경된 코드와 실행 결과입니다. Modifier에 확장함수의 순서만 바꾸었는데, 실행 결과는 전혀 다르다는 것을 볼 수 있습니다.

앞서 말씀드린 것처럼 Modifier에 순서대로 다른 Modifier를 적용하기 때문에 실행 결과가 전혀 다르게 나타납니다. 따라서, 의도하지 않게 결과가 나타난다면 Modifier에 확장함수를 적용한 순서를 의심해 볼 수 있습니다.

커스텀 컴포저블 함수에 Modifier 지원하기

커스텀 컴포저블에 Modifier 지원을 추가하는 것이 권장됩니다. Modifier를 지원하면, 다양한 설정(예: 테두리, 패딩, 배경 등)에 따라 여러 컴포저블을 생성할 필요 없이 단일 컴포저블에서 다양한 설정을 적용할 수 있습니다.

컴포저블에 Modifier 지원을 추가할 때는 파라미터 이름이 modifier이어야하며 파라미터 리스트 중 첫 번째 선택적 파라미터여야 합니다.

@Composable
fun CustomTextFiled(
		text: String,
		fontSize: Int,
		modifier: Modifier = Modifier
) {
		Text(
				modifier = modifier,
				text = text,
				fontSize = fontSize.sp
		)
}

Modifier 파라미터는 반드시 선택적이어야 하므로, 기본값으로 빈 Modifier 인스턴스를 지정해야 합니다.

@Preview
@Composable
fun PreviewCustomTextFiled() {
		CustomTextFiled(
				text = "Compose Modifier",
				fontSize = 30,
				modifier = Modifier
						.background(color = Color.Blue)
						.padding(all = 16.dp)
		)
}

@Composable
fun CustomTextFiled(
		text: String,
		fontSize: Int,
		modifier: Modifier = Modifier
) {
		Text(
				modifier = modifier,
				text = text,
				fontSize = fontSize.sp
		)
}

위 코드와 같이 CustomField 함수를 호출할 때 modifier를 전달할 수 있고 생략할 수도 있습니다.

Modifier간 연결하기

두 개 이상의 Modifier 객체를 연결하기 위해서 then 키워드를 활용할 수 있습니다.

val modifier = Modifier
		.padding(all = 16.dp)
		.border(width = 3.dp, color = Color.Black)
		
val secondModifier = Modifier.background(Color.Blue)

val combindModifier = modifier.then(secondModifier)

후기

UI를 구현하다 보면 fillMaxSize, fillMaxHeight, fillMaxWidth를 자주 사용하게 됩니다. 처음 사용할 때는 익숙하지 않아 원치 않는 결과가 나오는 경우가 종종 있습니다.

어떤 부분이 잘못되었는지 원인을 파악하기 위해 Modifier의 마지막에 background 확장 함수를 사용하여 현재 컴포즈의 사이즈와 설정을 확인해 수정할 수 있었습니다.

원하지 않는 결과가 나왔을 때는 background 확장 함수를 사용하여 디버깅하는 것을 추천합니다.

0개의 댓글