이제 가장 중요한 부분입니다. 원형 프로그래스 바가 증가할 때, 그 증가에 따라서 이미지도 이동해야 합니다. 이 과정을 고민할 때는 크게 리소스를 사용하지 않았습니다. 간단하게 원의 테두리 좌표를 구하면 되지 않을까 생각하면 삼각함수를 꺼내서 진행했습니다.
원의 좌표를 구하는 공식을 활용한 애니메이션 :: 마이구미
미리 알고 있어야 하는 값들이 존재합니다.
반지름과 각도만 안다면 원 테두리의 좌표는 쉽게 구할 수 있습니다. 우선 x 좌표를 구하는 공식을 알아봅시다.
x 좌표 구하기
y 좌표 구하기
다음과 같이 구하게 되면 원 테두리의 좌표는 다음과 같은 공식이 나옵니다.
이제 이것을 응용하여 이미지를 원형 프로그래스 바에 접근하게 하도록 해보겠습니다.
삼각함수를 사용해서 좌표를 가져오기 때문에 라디안이라는 것이 무엇인지 다시 알아보자.
1번 방법)
**= 180 (pixel) - cos(radian) * 140 (pixel)**
**= 180 (pixel) - sin(radian) * 140 (pixel)**
2번 방법)
**= 180 (pixel) - cos(radian) * 140 (pixel)**
**= 180 (pixel) + sin(radian) * 140 (pixel)**
그런데 이미지를 보니 조금 이상합니다. 안쪽으로 밀려난 이미지가 나타나는 것을 알 수 있습니다. 이러한 문제점은 canvas의 원리를 이해하면 쉽습니다. 좌표를 기준으로 아래와 오른쪽으로 그림을 그리게 되는데, 그렇게 되면 당연하게 영상처럼 안쪽으로 이미지를 그리게 됩니다. 그렇기 때문에 이미지의 크기인 너비와 높이를 알아서 너비를 x 좌표 값에서 빼고, 높이를 y 좌표 값에서 뺀다면 왼쪽 위로 이미지를 올릴 수 있습니다. 즉, 원 테두리 좌표에 정확하게 넣을 수 있는 것 입니다.
1번 방법)
**= 180 (pixel) - cos(radian) * 140 (pixel) - 24.px**
**= 180 (pixel) - sin(radian) * 140 (pixel) - 24.px**
2번 방법)
**= 180 (pixel) - cos(radian) * 140 (pixel) - 24.px**
**= 180 (pixel) + sin(radian) * 140 (pixel) - 24.px**
코드로 알아보면 다음과 같습니다. percent 값이 증가함으로써, degree 값이 변경되어지고, setImageBitmap 메서드가 호출됨으로써 이미지를 다시 그리게 되는 것입니다.
private var percent = 0F
private var degree = 0.0
private var imageBitmap: Bitmap? = null
private var x: Double = 0.0
private var y: Double = 0.0
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
...
imageBitmap?.let {
canvas.drawBitmap(it, x.toFloat(), y.toFloat(), null)
}
}
fun setPercent(percent: Float) {
this.percent = percent
degree = (percent * 120.0)
invalidate()
}
fun setImageBitmap(@DrawableRes image: Int) {
var radian: Double
radian = if (degree - 30 < 0) { // 1번 방법
Math.toRadians(30.0 - degree)
} else { // 2번 방법
Math.toRadians(degree - 30.0)
}
x = 180.px - cos(radian) * 140.px - 24.px
y = if (degree - 30 < 0) { // 1번 방법
180.px + sin(radian) * 140.px - 24.px
} else { // 2번 방법
180.px - sin(radian) * 140.px - 24.px
}
imageBitmap = ContextCompat.getDrawable(context, image)?.run {
toBitmap(48.px.toInt(), 48.px.toInt())
}
invalidate()
}
이러한 방법과 똑같이 반대쪽도 진행한다면 진행했던 “모티부” 서비스의 원형 프로그래스 바 커스텀 뷰 작성을 완성하게 된다.
디자인이 나왔을 때, 당황을 했다. 처음보는 프로그래스 바 디자인이었고, 커스텀 뷰를 해봤지만 canvas를 사용하여 흰 도화지에 그림 그려본 적은 없었기 때문이다. 잘해낼 수 있을까.. 고민을 많이 했지만, 나는 디자인이 해당 디자인을 할 수 있냐고 물어봤을 때, 당시에는 고민하지도 않고 “네 할 수 있습니다.” 라고 답했다. 자신 있었다. 할 수 있을 것 같은 자신감이 그 순간에는 계속 들었다. 실제로 진행하면서 좌우반전, 이미지 canvas로 그리기, 이미지 움직이기 등 다양한 문제를 직면했지만 계속해서 고민하고 레퍼런스를 찾아보면서 해결할 수 있었다.
개발에 있어서 걸림돌이 되는 것은 실력인 것 같다. 지금도 많이 부족한 원형 프로그래스 바라고 생각한다. 만약에 실력이 더 출중했다면, 디자인 요구에 맞는 완벽한 원형 프로그래스 바를 만들 수 있을 것 같았다. 그래도 이번 원형 프로그래스 바를 제작하면서 느낀점은 해보지 않고 포기하려는 것은 실패하는 것보다 참담하다고 생각한다. 실패를 겪고 그 문제점을 고민해보는 것이 개발자라면 항상해야하는 고민이라고 생각한다. 이번 “모티부”라는 서비스를 만들면서 한 단계 성장할 수 있는 경험이여서 좋은 경험이었다.