이번에 만들어볼 것은 사용자의 터치 입력에따라 회전하는 핸들뷰다. 다양하게 활용할 수 있는데, 회사에서 뽑기 기계를 만들어보자는 아이디어에서 삼각함수로 뽀리면 되겠는데?! 라는 생각에서 만들어서 검증해보았다.
xml은 터치 입력을 받을 view_touch와 ImageView인 handle 단 두개로 이루어져있다.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/view_touch"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#eee"
/>
<ImageView
android:id="@+id/handle"
android:layout_width="160dp"
android:layout_height="160dp"
android:src="@drawable/handle"/>
</FrameLayout>
center에는 touch view의 가운데 지점을 저장하고, handle 이미지 뷰를 정 중앙으로 옮긴다.
val viewTouch = findViewById<View>(R.id.view_touch)
val handle = findViewById<ImageView>(R.id.handle)
val center = PointF()
viewTouch.viewTreeObserver.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
center.x = viewTouch.x + viewTouch.width / 2
center.y = viewTouch.y + viewTouch.height / 2
handle.x = center.x - handle.width / 2
handle.y = center.y - handle.height / 2
viewTouch.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
})
우리가 궁금한건 center가 원점, 사용자가 view를 터치한 좌표가 x,y라고 할때 중심으로부터 x,y로 향하는 선과 x축이 이루는 각도 θ의 값이다. 이 각도를 degree로 변환하여 rotation에 할당하면 된다.
이럴때 atan2 함수를 사용할 수 있는데, atan2는 역탄젠트 값(radian)을 반환하는데, 이것은 아래 그림처럼 정확히 우리가 원하는 θ의 값이다.
var prevDegree = 0.0
viewTouch.setOnTouchListener { v, event ->
val dX = event.x - center.x.toDouble()
val dY = event.y - center.y.toDouble()
var degree = Math.toDegrees(atan2(dY, dX))
when (event.action) {
MotionEvent.ACTION_DOWN -> {
prevDegree = degree
}
MotionEvent.ACTION_MOVE -> {
handle.rotation = (handle.rotation + (degree - prevDegree)).toFloat()
prevDegree = degree
}
}
return@setOnTouchListener true
}
dX, dY는 위 그림에서 x,y에 해당된다.
atan2(dY, dX)의 결과값 단위가 -PI와 PI사이의 Radian 값이기 때문에 이를 각도로 변환하는 과정이 한번 더 필요하다.
터치를 하기 시작했을때(ACTION_DOWN) 현재 각도를 저장, 드래그하며 움직일때(ACTION_MOVE) 이전각도와 현재각도의 차이만큼 회전값(rotation)에 더해주면 핸들이 자연스럽게 손가락을 따라 움직이기 시작할 것이다.
'프로그래밍 > Android' 카테고리의 다른 글
[안드로이드] HiltWorker 오류 Could not create Worker 해결방법 (0) | 2022.09.13 |
---|---|
[안드로이드] WorkManager Worker 디버깅하기 (0) | 2022.09.13 |
[안드로이드] 실시간 네크워크 상태 callbackFlow를 이용해 만들어보자! (Youtube 인터넷 연결처럼 구현) (0) | 2022.08.13 |
[Android] 멋진 오픈소스 프로젝트 모음 - Awesome Android Kotlin Apps (0) | 2022.08.11 |
[Bitrise Cli] 리눅스 서버에서 CI/CD pipeline 직접 구축해보기 (2) (0) | 2022.08.07 |