Android에서 Canvas가 필요한 이유
Canvas는 Android에서 Custom UI를 간편하게 그리기 위한 다양한 API를 제공해준다. Canvas에서 제공해주는 API를 사용하면 도형, 텍스트를 그릴 수 있고, 애니메이션 또한 만들 수 있다.
또한 Canvas는 그려야 할 도형들이 많을 때, Composable 여러개를 사용해 그리는 것에 비해 자원을 효율적으로 사용한다. 이 때문에 만약 화면이 여러 도형으로 구성되어있고, 도형의 상태(크기, 색상 등)을 계속해서 변경시켜야 하는 작업에서는 Canvas를 사용하는 것이 훨씬 리소스를 적게 사용한다.
이번 글에서는 Jetpack Compose에서 Canvas를 사용하는 간단한 방법에 대해 살펴볼 것이다.
Jetpack Compose에서 Canvas 사용하기
Android의 Jetpack Compose에서 Canvas를 사용하기 위해서는 Canvas Composable을 사용하면 된다. Canvas는 두개의 파라미터를 받는다. 하나는 modifier이고, 다른 하나는 onDraw이다. modifier에서 Canvas의 사이즈나, 모양 등을 설정하고, onDraw에서는 만들어진 Canvas에서 컴포넌트를 어떻게 그릴 것인지 설정한다.
정중앙에 정사각형을 그리는 간단한 Canvas Composable을 만들면서 해당 구성요소에 대해 살펴보도록 하자.
@Preview(showBackground = true)
@Composable
fun CanvasExample() {
Canvas(
modifier = Modifier.size(300.dp),
onDraw = {
drawRect(
color = Color.Blue,
topLeft = Offset(100.dp.toPx(), 100.dp.toPx()),
size = Size(100.dp.toPx(), 100.dp.toPx())
)
}
)
}
이 CanvasExample은 사이즈를 300dp로 설정하고, 왼쪽 위 지점을 (100dp, 100dp)로 해서 100dp 크기의 정사각형을 그린다. 따라서 이 Canvas는 다음과 같이 생성된다.
Canvas를 사용하는 또 다른 방법
Canvas Composable 내부를 보면 다음과 같이 구성되어 있다.
@Composable
fun Canvas(modifier: Modifier, onDraw: DrawScope.() -> Unit) =
Spacer(modifier.drawBehind(onDraw))
즉, 위에서 만든 Canvas Composable은 Spacer을 만들고 Spacer의 modifier로 drawBehind 구성요소와 함께 자신이 만든 onDraw함수를 넘기고 있다. Spacer는 단순한 빈공간을 만드는데 사용되는 Composable이므로, drawBehind가 Canvas를 그리기 위한 주요 역할을 하는 것을 알 수 있다.
이를 응용해 아래와 같은 Composable을 만들어보도록 하자. Box를 만든 후 내부에 Canvas를 사용해 네모를 그리고 "조세영의 KotlinWorld"라는 글자를 넣는다.
@Preview(showBackground = true)
@Composable
fun CanvasExample() {
Box(modifier = Modifier
.size(300.dp)
.drawBehind {
drawRect(
color = Color.Blue,
topLeft = Offset(50.dp.toPx(), 50.dp.toPx()),
size = Size(200.dp.toPx(), 200.dp.toPx())
)
}
) {
Text(
modifier = Modifier.align(Alignment.Center),
text = "조세영의 Kotlin World",
color = Color.White
)
}
}
그러면 다음과 같은 결과가 나오는 것을 볼 수 있다.
즉, 어떠한 Composable에서도 modifier로 drawBehind 를 통해 Canvas를 사용할 수 있음을 알 수 있다.
정리
Compose는 기본적으로 Canvas Composable을 사용해 Canvas 사용이 가능하지만, 다른 Composable들에서도 modifier에 drawBehind를 사용해 Canvas를 사용할 수 있다.