Open1
自作AndroidアプリのTips
ズーム機能を実装する
概要
カメラの映像を表示しているViewに対してピンチイン・ピンチアウトによりズーム機能を実装する。
ズームを行い倍率が等倍より大きくなっている場ありのみドラッグによる画面の移動ができるものとし、ダブルタップにより倍率と表示位置のリセットを行う。
実装
ScaleGestureDetector
スケールの変更を検知するためにScaleGestureDetectorの実装を行う。
今回の要件では用意されている機能の一部のみ使用するため、公式ドキュメントの記載に従ってサブクラスであるSimpleOnScaleGestureListenerを継承する。
package com.tatsuya.babymonitor.ui.zoom
import android.view.ScaleGestureDetector
import android.view.View
class ZoomScaleGestureListener(private val view: View) : ScaleGestureDetector.SimpleOnScaleGestureListener() {
private var scaleFactor = 1.0f
private var focusX = 0f
private var focusY = 0f
/**
* スケールの変更を検知した時点で1度だけ発火
* 倍率変更時の基準となる位置を記憶
*/
override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
focusX = detector.focusX
focusY = detector.focusY
return true
}
/**
* スケールの変更が行われている間定期的に発火
* 倍率の指定と位置の固定(デフォルト値から変更しない)を行う
*/
override fun onScale(detector: ScaleGestureDetector): Boolean {
scaleFactor *= detector.scaleFactor
scaleFactor = 1.0f.coerceAtLeast(scaleFactor.coerceAtMost(5.0f))
view.scaleX = scaleFactor
view.scaleY = scaleFactor
view.pivotX = focusX
view.pivotY = focusY
return true
}
}
GestureDetector
ドラッグとダブルタップの検知のためにGestureDetectorの実装を行う。今回の要件では用意されている機能の一部のみ使用するため、公式ドキュメントの記載に従ってサブクラスであるSimpleOnGestureListenerを継承する。
package com.tatsuya.babymonitor.ui.zoom
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
class ZoomGestureListener(private val view: View) : GestureDetector.SimpleOnGestureListener() {
/**
* タッチの検知開始イベント(何もしない)
*/
override fun onDown(e: MotionEvent): Boolean {
return true
}
/**
* ダブルタップを検知して、倍率と位置をリセットする
*/
override fun onDoubleTap(e: MotionEvent): Boolean {
view.scaleX = 1.0f
view.scaleY = 1.0f
view.translationX = 0f
view.translationY = 0f
return true
}
/**
* ドラッグ(スクロール)を検知して、表示位置を変更する
* ただし、倍率が等倍以下の場合は移動させない
*/
override fun onScroll(
e1: MotionEvent?,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
if (view.scaleX <= 1.0f && view.scaleY <= 1.0f) {
return true
}
view.translationX -= distanceX
view.translationY -= distanceY
return true
}
}