From fe3710510de5cbb5d72e1165d48eb5b06a4530fe Mon Sep 17 00:00:00 2001 From: darthpaul Date: Sat, 25 Jun 2022 22:42:47 +0100 Subject: [PATCH] add pinch to zoom support --- .../PinchToZoomOnScaleGestureListener.kt | 19 ++++++++++++++++++ .../camera/helpers/ZoomCalculator.kt | 20 +++++++++++++++++++ .../camera/implementations/CameraXPreview.kt | 5 +++++ 3 files changed, 44 insertions(+) create mode 100644 app/src/main/kotlin/com/simplemobiletools/camera/helpers/PinchToZoomOnScaleGestureListener.kt create mode 100644 app/src/main/kotlin/com/simplemobiletools/camera/helpers/ZoomCalculator.kt diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/PinchToZoomOnScaleGestureListener.kt b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/PinchToZoomOnScaleGestureListener.kt new file mode 100644 index 00000000..3289e433 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/PinchToZoomOnScaleGestureListener.kt @@ -0,0 +1,19 @@ +package com.simplemobiletools.camera.helpers + +import android.view.ScaleGestureDetector +import androidx.camera.core.CameraControl +import androidx.camera.core.CameraInfo + +class PinchToZoomOnScaleGestureListener( + private val cameraInfo: CameraInfo, + private val cameraControl: CameraControl, +) : ScaleGestureDetector.SimpleOnScaleGestureListener() { + private val zoomCalculator = ZoomCalculator() + + override fun onScale(detector: ScaleGestureDetector): Boolean { + val zoomState = cameraInfo.zoomState.value ?: return false + val zoomRatio = zoomCalculator.calculateZoomRatio(zoomState, detector.scaleFactor) + cameraControl.setZoomRatio(zoomRatio) + return true + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/ZoomCalculator.kt b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/ZoomCalculator.kt new file mode 100644 index 00000000..1e2aa294 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/ZoomCalculator.kt @@ -0,0 +1,20 @@ +package com.simplemobiletools.camera.helpers + +import androidx.camera.core.ZoomState + +class ZoomCalculator { + + fun calculateZoomRatio(zoomState: ZoomState, pinchToZoomScale: Float): Float { + val clampedRatio = zoomState.zoomRatio * speedUpZoomBy2X(pinchToZoomScale) + // Clamp the ratio with the zoom range. + return clampedRatio.coerceAtLeast(zoomState.minZoomRatio).coerceAtMost(zoomState.maxZoomRatio) + } + + private fun speedUpZoomBy2X(scaleFactor: Float): Float { + return if (scaleFactor > 1f) { + 1.0f + (scaleFactor - 1.0f) * 2 + } else { + 1.0f - (1.0f - scaleFactor) * 2 + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt b/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt index da933c64..e3c23c16 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt @@ -14,6 +14,7 @@ import android.view.GestureDetector import android.view.GestureDetector.SimpleOnGestureListener import android.view.MotionEvent import android.view.OrientationEventListener +import android.view.ScaleGestureDetector import android.view.Surface import androidx.appcompat.app.AppCompatActivity import androidx.camera.core.* @@ -44,6 +45,8 @@ import com.simplemobiletools.camera.extensions.config import com.simplemobiletools.camera.extensions.toAppFlashMode import com.simplemobiletools.camera.extensions.toCameraXFlashMode import com.simplemobiletools.camera.helpers.MediaSoundHelper +import com.simplemobiletools.camera.helpers.PinchToZoomOnScaleGestureListener +import com.simplemobiletools.camera.helpers.ZoomCalculator import com.simplemobiletools.camera.interfaces.MyPreview import com.simplemobiletools.commons.extensions.showErrorToast import com.simplemobiletools.commons.extensions.toast @@ -280,6 +283,7 @@ class CameraXPreview( // source: https://stackoverflow.com/a/60095886/10552591 private fun setupZoomAndFocus() { Log.i(TAG, "camera controller: ${previewView.controller}") + val scaleGesture = camera?.let { ScaleGestureDetector(activity, PinchToZoomOnScaleGestureListener(it.cameraInfo, it.cameraControl)) } val gestureDetector = GestureDetector(activity, object : SimpleOnGestureListener() { override fun onSingleTapConfirmed(event: MotionEvent): Boolean { return camera?.cameraInfo?.let { @@ -306,6 +310,7 @@ class CameraXPreview( previewView.setOnTouchListener { _, event -> Log.i(TAG, "setOnTouchListener: x=${event.x}, y=${event.y}") gestureDetector.onTouchEvent(event) + scaleGesture?.onTouchEvent(event) true } }