이번 글에서 다룰 내용
이번 글에서는 Canvas의 drawRect를 사용해 사각형을 그리는 방법에 대해 깊게 다룬다. 두가지 함수가 지원되는 drawRect와 drawRect의 각 파라미터가 어떤 역할을 하는지 알아본다.
Color 객체를 사용하는 drawRect함수
먼저 Color 객체를 사용하는 drawRect함수부터 살펴본다.
fun drawRect(
color: Color,
topLeft: Offset = Offset.Zero,
size: Size = this.size.offsetSize(topLeft),
/*@FloatRange(from = 0.0, to = 1.0)*/
alpha: Float = 1.0f,
style: DrawStyle = Fill,
colorFilter: ColorFilter? = null,
blendMode: BlendMode = DefaultBlendMode
)
해당 구현체의 각 파라미터는 다음과 같은 역할을 한다.
- color: 사각형의 색상을 설정
- topLeft: 사각형 왼쪽 상단 부분 꼭지점의 좌표를 설정
- size: 사각형의 크기를 설정
- alpha: color의 불투명도를 설정. 1이면 완전히 불투명, 0이면 완전히 투명
- style: 사각형을 완전히 채울 것인지, 모서리만 그릴 것인지 설정
- colorFilter: 필터를 설정
- blendMode: 블랜더 설정
자 이제 이 파라미터들을 사용해 사각형을 그려보자.
drawRect 사용해보기
간단한 정사각형 그리기
300dp의 Canvas가 있다고 했을 때, 정중앙에 100dp 크기의 파란색 정사각형을 그리려면 다음과 같이 만들면 된다.
@Preview(showBackground = true)
@Composable
fun KotlinWorldDrawRectExample() {
Canvas(
modifier = Modifier
.size(300.dp)
.background(Color.White),
onDraw = {
drawRect(
color = Color.Blue,
topLeft = Offset(100.dp.toPx(), 100.dp.toPx()),
size = Size(100.dp.toPx(), 100.dp.toPx()),
alpha = 0.5f
)
}
)
}
Canvas의 크기가 300dp이므로, 중앙 지점은 150dp이다. 이에 100dp 크기의 정사각형이므로 정사각형의 왼쪽 상단 시작점은 (150-50)dp로 잡아야 한다. 따라서, 좌표계의 x, y좌표를 모두 100.dp.toPx()로 잡아서 사각형의 시작 지점을 만든다음, 사각형의 크기를 100dp로 잡으면 캔버스 정중앙에 100dp 크기의 파란색 정사각형을 그릴 수 있다.
따라서 위 코드에서 나온 Preview는 아래와 같이 나타난다.
투명도 있는 정사각형 그리기
투명도 있는 정사각형을 그리려면 alpha 속성을 사용하면 된다. alpha 가 1이면 완전히 불투명하고, 0이면 완전히 투명해진다. 자 투명도를 0.5로 만들어보자.
@Preview(showBackground = true)
@Composable
fun DrawRect() {
Canvas(
modifier = Modifier
.size(300.dp)
.background(Color.White),
onDraw = {
drawRect(
color = Color.Blue,
topLeft = Offset(100.dp.toPx(), 100.dp.toPx()),
size = Size(100.dp.toPx(), 100.dp.toPx()),
alpha = 0.5f
)
}
)
}
그러면 다음과 같은 결과가 나온다.
파란색에 투명도가 더해진 것을 확인할 수 있다.
style 사용해 도명 채울지 아니면 모서리만 그릴지 결정하기
style은 Fill과 Stroke두가지가 지원된다. 기본값은 Fill로 도형이 완전히 채워지는 결과가 나오며, Stroke은 모서리만 그리는 것이다. 예를 들어 10dp 굵기의 모서리를 추가하려면 다음과 같이 만들면 된다.
@Preview(showBackground = true)
@Composable
fun DrawRect() {
Canvas(
modifier = Modifier
.size(300.dp)
.background(Color.White),
onDraw = {
drawRect(
color = Color.Blue,
topLeft = Offset(100.dp.toPx(), 100.dp.toPx()),
size = Size(100.dp.toPx(), 100.dp.toPx()),
alpha = 0.5f,
style = Stroke(width = 10.dp.toPx())
)
}
)
}
그러면 모서리가 생긴 것을 확인할 수 있다.
colorFilter와 blendMode 사용해 색상에 효과 더하기
colorFilter와 blendMode는 색상에 효과를 더하기 위한 프로퍼티이다. colorFilter는 각 픽셀에 어떤 변화를 줄지를 설정하며, BlendMode를 사용해서 원 픽셀을 받아서 각 픽셀에 어떤 변화를 줄지 알고리즘을 설정할 수 있다.
안드로이드는 기본적으로 다양한 BlendMode를 지원하며, 해당 BlendMode에 대해 이 글에서 일일히 다루기는 어렵다.
간단히 colorFilter을 주는 예제만 보도록 하자. 아래와 같이 간단히 lighting Color Filter을 주면 파란색이 연한 보라색으로 바뀌는 것을 볼 수 있다.
@Preview(showBackground = true)
@Composable
fun DrawRect() {
Canvas(
modifier = Modifier
.size(300.dp)
.background(Color.White),
onDraw = {
drawRect(
color = Color.Blue,
topLeft = Offset(100.dp.toPx(), 100.dp.toPx()),
size = Size(100.dp.toPx(), 100.dp.toPx()),
colorFilter = ColorFilter.lighting(Color.Blue, Color.Gray)
)
}
)
}
drawRect brush와 함께 사용하기
drawRect에는 한 가지 함수가 더 있다. 바로 Brush를 사용해 두개 이상의 색상이 사각형에 필요할 때 사용하는 함수이다. brush를 사용하면 더이상 color을 사용하지 않는다. 아래는 함수가 입력 받는 파라미터들인데, 위의 drawRect의 color만 brush로 바뀐 것을 알 수 있다.
fun drawRect(
brush: Brush,
topLeft: Offset = Offset.Zero,
size: Size = this.size.offsetSize(topLeft),
/*FloatRange(from = 0.0, to = 1.0)*/
alpha: Float = 1.0f,
style: DrawStyle = Fill,
colorFilter: ColorFilter? = null,
blendMode: BlendMode = DefaultBlendMode
)
예를 들어, 아래와 같이 linearGradient를 사용해 왼쪽 위에는 파란색이, 오른쪽 아래에는 짙은 회색이 가도록 만들 수 있다. 색 변화가 더 잘보이도록 하기 위해 가로 길이를 200dp로 늘렸다.
@Preview(showBackground = true)
@Composable
fun DrawRectBrush() {
Canvas(
modifier = Modifier
.size(300.dp)
.background(Color.White),
onDraw = {
drawRect(
brush = Brush.linearGradient(listOf(Color.Blue, Color.DarkGray)),
topLeft = Offset(50.dp.toPx(), 100.dp.toPx()),
size = Size(200.dp.toPx(), 100.dp.toPx()),
)
}
)
}
그러면 아래와 같은 사각형이 나오게 된다.
이 외에도 중앙에서 바깥으로 색 변화를 주는 radialGradient 같은 Brush를 사용할 수도 있다. Brush에는 종류가 매우 많고 2개 이상의 색상을 입력 받을 수도 있다.