Compose의 Canvas와 Native Canvas의 관계
Compose의 Canvas는 내부적으로는 xml에서 사용하던 Canvas와 같은 Canvas를 사용한다. 즉, Compose 또한 NativeCanvas를 사용한다. 우리가 Canvas에서 drawRect 등을 사용해 도형을 그리면, 해당 함수는 Native Canvas에서 drawRect를 통해 도형을 그리는 것과 같은 동작을 하는 것이다.
Compose Canvas의 한계
Compose Canvas는 Composable로 제공되는 Canvas에서 제공되는 API만을 사용할 수 있기 때문에, 기존 xml 기반의 Canvas에 비해 한정된 기능만을 제공한다. 이는 출시된지 얼마 되지 않은 Compose의 한계로, Compose에서는 종종 이런 상황이 발생한다. 대표적으로 TextView에서는 문자열 앞쪽 중간 뒤 모두 말줄임(ellipsis)이 제공된 것에 비해, Compose의 Text는 ellipsis를 문자열 마지막에 대해서만 제공하고, 얼마 전까지 marquee도 제공되지 않아 흐름 효과를 구현하는데 어려움이 있었다.
Compose Canvas에서 Native Canvas 접근하기
이를 해결하기 위해 Compose는 AndroidView와 같은 Composable을 제공해 기존 View를 사용할 수 있도록 한다.
예를 들어 다음과 TextView를 사용할 수 있다.
AndroidView(
factory = {
TextView(it)
}
)
하지만, Canvas는 내부적으로는 같은 객체를 사용하고 있기 때문에 Canvas Composable 내부에서 해당 객체에 접근할 수 있는 방법을 제공한다.
Canvas Composable에서 Native Canvas에 접근하는 방법은 drawContext.canvas.nativeCanvas를 통해 접근 가능하다. 접근을 한 이후에는 기존 Canvas에서 제공하던 모든 API를 사용할 수 있게 된다.
@Preview(showBackground = true)
@Composable
fun CanvasAccessNativeCanvas() {
Canvas(
modifier = Modifier
.size(300.dp)
) {
drawContext.canvas.nativeCanvas.apply {
// 기존 Canvas의 로직 사용
}
}
}
한번 간단한 사각형을 그려보도록 하자. 아래와 같이 코드를 구성하면
결과가 다음과 같이 나온다.