getX()とgetRawX()
MotionEventにはgetX()とgetRawX()という異なるメソッドがあります。
(もちろん同様にy座標に関するメソッドもあります)
この2つのメソッドの違いは、getX()はEventの対象となるViewのローカル座標、getRawX()はスクリーン上の座標を取得するという点になります。
getRawX()とgetRawX(index)
API29からgetRaw(index)というメソッドが追加されました。
MotionEventではタッチされている座標(pointer)が複数ある場合があり、indexを指定することでpointerごとの座標を取得することができます。
しかし、getRawX(index)はAPI29から追加されたメソッドのため、API29未満では自分で計算を行うことになります。
API29未満にもgetX(index)というメソッドがあります、これは指定したindexのpointerのローカル座標を取得するメソッドです。このメソッドを利用して計算をします。
ローカル座標からスクリーン座標への変換
具体的なコードは以下になります。
Viewが回転、拡大、縮小していた場合にも正しい座標が取得できるようになっています。
回転、拡大、縮小が不要な場合には該当のコードを削除してください。
private fun getRawPoint(view: View, event: MotionEvent, index: Int): PointF {
val location = intArrayOf(0, 0)
view.getLocationOnScreen(location)
var x = event.getX(index) * view.scaleX
var y = event.getY(index) * view.scaleY
var angle = Math.toDegrees(atan2(y.toDouble(), x.toDouble()))
angle += view.rotation.toDouble()
val length = hypot(x, y)
x = (length * cos(Math.toRadians(angle))).toFloat() + location[0]
y = (length * sin(Math.toRadians(angle))).toFloat() + location[1]
return PointF(x, y)
}
scaleが変更されていた場合を考慮し、x, yの値にscaleをかけています。
また、回転していた場合を考慮し、アークタンジェントを求めるatan2(y, x)を利用して座標から角度を求めrotationと合計しています。
解説のため下図を用意しました。
rotationでαの角度、atan2(y, x)でβの角度を求めています。
lengthが三角関数の斜辺となりα + βが三角関数のθとなるのであとはsin、cosで座標が求められますね。
API29未満でMotionEventからスクリーン座標を取得したいときにお使いください。