시작점과 현재 기준점을 연결하지 않았을 경우의 문제
아래의 Path를 보자. 아래 Path의 마지막 줄의 lineTo 함수는 이전 기준점인 (300, 100)와 (100, 100)을 잇는 직선을 생성한다.
val path = Path().apply {
moveTo(100.dp.toPx(), 100.dp.toPx()) // 시작 지점 (100, 100)
lineTo(100.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 100.dp.toPx())
lineTo(100.dp.toPx(), 100.dp.toPx()) // (300, 100)과 (100, 100)을 잇는 직선 생성
}
이 Path는 정상적으로 사각형을 만들 것으로 보여 문제가 없을 것으로 보인다.
하지만, 한번 이를 drawPath함수를 통해 Stroke 모드로 그려보자.
@Preview(widthDp = 400, heightDp = 400)
@Composable
fun DrawRectWithPath() {
Canvas(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
onDraw = {
val path = Path().apply {
moveTo(100.dp.toPx(), 100.dp.toPx()) // 시작 지점 옮기기
lineTo(100.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 100.dp.toPx())
lineTo(100.dp.toPx(), 100.dp.toPx())
}
drawPath(
path = path,
color = Color.Blue,
style = Stroke(width = 10.dp.toPx())
)
}
)
}
그러면 다음과 같은 화면이 나온다.

위 화면에서 왼쪽 위 꼭지점이 살짝 네모 형태가 되는 것을 볼 수 있다.
이렇게 왼쪽 위 꼭지점이 살짝 네모 형태가 되는 이유는 시작점(100, 100)과 lineTo 를 통해 만든 새로운 기준점이 같다고 해서, 도형이 만들어지는 것이 아니기 때문이다. 위 Path는 직선 4개로 이루어져 있을 뿐이며, drawPath는 각 직선을 그릴 뿐이다. 이를 해결하기 위해서는 Path를 닫아야(close) 한다
close() 함수 사용해 Path 닫기
먼저 Path의 close가 무엇을 하는지에 대한 설명을 보자.
/**
* Closes the last subpath, as if a straight line had been drawn
* from the current point to the first point of the subpath.
*/
fun close()
이를 요약하면, 마지막 하위 경로를 시작점까지 연결해 닫는다는 뜻이다.
따라서 위 함수에서 마지막 기준점 (100, 100)과 시작점 (100, 100) 사이에 직선을 만들어 닫으려면 아래와 같이 쓰면 된다.
@Preview(widthDp = 400, heightDp = 400)
@Composable
fun DrawRectWithPath() {
Canvas(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
onDraw = {
val path = Path().apply {
moveTo(100.dp.toPx(), 100.dp.toPx()) // 시작 지점 옮기기
lineTo(100.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 100.dp.toPx())
lineTo(100.dp.toPx(), 100.dp.toPx())
close()
}
drawPath(
path = path,
color = Color.Blue,
style = Stroke(width = 10.dp.toPx())
)
}
)
}
그러면 왼쪽 위에 빈 공간이 사라지는 것을 볼 수 있다.

close 사용해 마지막 직선 대체하기
이를 응용하면, 마지막 기준점이 (300, 100)이고, 시작점이 (100, 100)일 때 close()를 사용해 닫힌 도형을 만들어낼 수 있다.
@Preview(widthDp = 400, heightDp = 400)
@Composable
fun DrawRectWithPath() {
Canvas(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
onDraw = {
val path = Path().apply {
moveTo(100.dp.toPx(), 100.dp.toPx()) // 시작 지점 옮기기
lineTo(100.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 100.dp.toPx())
close()
}
drawPath(
path = path,
color = Color.Blue,
style = Stroke(width = 10.dp.toPx())
)
}
)
}
이렇게 해도 그림2와 같은 도형이 나온다.

시작점과 현재 기준점을 연결하지 않았을 경우의 문제
아래의 Path를 보자. 아래 Path의 마지막 줄의 lineTo 함수는 이전 기준점인 (300, 100)와 (100, 100)을 잇는 직선을 생성한다.
val path = Path().apply {
moveTo(100.dp.toPx(), 100.dp.toPx()) // 시작 지점 (100, 100)
lineTo(100.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 100.dp.toPx())
lineTo(100.dp.toPx(), 100.dp.toPx()) // (300, 100)과 (100, 100)을 잇는 직선 생성
}
이 Path는 정상적으로 사각형을 만들 것으로 보여 문제가 없을 것으로 보인다.
하지만, 한번 이를 drawPath함수를 통해 Stroke 모드로 그려보자.
@Preview(widthDp = 400, heightDp = 400)
@Composable
fun DrawRectWithPath() {
Canvas(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
onDraw = {
val path = Path().apply {
moveTo(100.dp.toPx(), 100.dp.toPx()) // 시작 지점 옮기기
lineTo(100.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 100.dp.toPx())
lineTo(100.dp.toPx(), 100.dp.toPx())
}
drawPath(
path = path,
color = Color.Blue,
style = Stroke(width = 10.dp.toPx())
)
}
)
}
그러면 다음과 같은 화면이 나온다.

위 화면에서 왼쪽 위 꼭지점이 살짝 네모 형태가 되는 것을 볼 수 있다.
이렇게 왼쪽 위 꼭지점이 살짝 네모 형태가 되는 이유는 시작점(100, 100)과 lineTo 를 통해 만든 새로운 기준점이 같다고 해서, 도형이 만들어지는 것이 아니기 때문이다. 위 Path는 직선 4개로 이루어져 있을 뿐이며, drawPath는 각 직선을 그릴 뿐이다. 이를 해결하기 위해서는 Path를 닫아야(close) 한다
close() 함수 사용해 Path 닫기
먼저 Path의 close가 무엇을 하는지에 대한 설명을 보자.
/**
* Closes the last subpath, as if a straight line had been drawn
* from the current point to the first point of the subpath.
*/
fun close()
이를 요약하면, 마지막 하위 경로를 시작점까지 연결해 닫는다는 뜻이다.
따라서 위 함수에서 마지막 기준점 (100, 100)과 시작점 (100, 100) 사이에 직선을 만들어 닫으려면 아래와 같이 쓰면 된다.
@Preview(widthDp = 400, heightDp = 400)
@Composable
fun DrawRectWithPath() {
Canvas(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
onDraw = {
val path = Path().apply {
moveTo(100.dp.toPx(), 100.dp.toPx()) // 시작 지점 옮기기
lineTo(100.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 100.dp.toPx())
lineTo(100.dp.toPx(), 100.dp.toPx())
close()
}
drawPath(
path = path,
color = Color.Blue,
style = Stroke(width = 10.dp.toPx())
)
}
)
}
그러면 왼쪽 위에 빈 공간이 사라지는 것을 볼 수 있다.

close 사용해 마지막 직선 대체하기
이를 응용하면, 마지막 기준점이 (300, 100)이고, 시작점이 (100, 100)일 때 close()를 사용해 닫힌 도형을 만들어낼 수 있다.
@Preview(widthDp = 400, heightDp = 400)
@Composable
fun DrawRectWithPath() {
Canvas(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
onDraw = {
val path = Path().apply {
moveTo(100.dp.toPx(), 100.dp.toPx()) // 시작 지점 옮기기
lineTo(100.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 300.dp.toPx())
lineTo(300.dp.toPx(), 100.dp.toPx())
close()
}
drawPath(
path = path,
color = Color.Blue,
style = Stroke(width = 10.dp.toPx())
)
}
)
}
이렇게 해도 그림2와 같은 도형이 나온다.
