From efe6556fc244c1e1cf2ba9cdcfd0526cf9dc6a61 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Wed, 23 Aug 2023 15:39:24 +0200 Subject: [PATCH] feat: Implement `enableZoomGesture` on Android --- .../java/com/mrousavy/camera/CameraView.kt | 33 +++++++++++++++---- .../com/mrousavy/camera/CameraViewManager.kt | 7 ++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/android/src/main/java/com/mrousavy/camera/CameraView.kt b/android/src/main/java/com/mrousavy/camera/CameraView.kt index c856aaa..3d3c574 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraView.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraView.kt @@ -8,6 +8,7 @@ import android.content.res.Configuration import android.hardware.camera2.CameraManager import android.util.Log import android.util.Size +import android.view.ScaleGestureDetector import android.view.Surface import android.view.View import android.widget.FrameLayout @@ -16,8 +17,8 @@ import com.facebook.react.bridge.ReadableMap import com.mrousavy.camera.extensions.containsAny import com.mrousavy.camera.extensions.installHierarchyFitter import com.mrousavy.camera.frameprocessor.FrameProcessor -import com.mrousavy.camera.parsers.PixelFormat import com.mrousavy.camera.parsers.Orientation +import com.mrousavy.camera.parsers.PixelFormat import com.mrousavy.camera.parsers.PreviewType import com.mrousavy.camera.parsers.Torch import com.mrousavy.camera.parsers.VideoStabilizationMode @@ -80,6 +81,7 @@ class CameraView(context: Context) : FrameLayout(context) { var torch: Torch = Torch.OFF var zoom: Float = 1f // in "factor" var orientation: Orientation? = null + var enableZoomGesture: Boolean = false // private properties private var isMounted = false @@ -102,9 +104,6 @@ class CameraView(context: Context) : FrameLayout(context) { internal val outputOrientation: Orientation get() = orientation ?: inputOrientation - private var minZoom: Float = 1f - private var maxZoom: Float = 1f - init { this.installHierarchyFitter() setupPreviewView() @@ -167,10 +166,11 @@ class CameraView(context: Context) : FrameLayout(context) { val shouldReconfigurePreview = changedProps.containsAny(propsThatRequirePreviewReconfiguration) val shouldReconfigureSession = shouldReconfigurePreview || changedProps.containsAny(propsThatRequireSessionReconfiguration) val shouldReconfigureFormat = shouldReconfigureSession || changedProps.containsAny(propsThatRequireFormatReconfiguration) - val shouldReconfigureZoom = /* TODO: When should we reconfigure this? */ shouldReconfigureSession || changedProps.contains("zoom") - val shouldReconfigureTorch = /* TODO: When should we reconfigure this? */ shouldReconfigureSession || changedProps.contains("torch") + val shouldReconfigureZoom = shouldReconfigureSession || changedProps.contains("zoom") + val shouldReconfigureTorch = shouldReconfigureSession || changedProps.contains("torch") val shouldUpdateOrientation = /* TODO: When should we reconfigure this? */ shouldReconfigureSession || changedProps.contains("orientation") val shouldCheckActive = shouldReconfigureFormat || changedProps.contains("isActive") + val shouldReconfigureZoomGesture = changedProps.contains("enableZoomGesture") if (shouldReconfigurePreview) { setupPreviewView() @@ -194,6 +194,9 @@ class CameraView(context: Context) : FrameLayout(context) { if (shouldUpdateOrientation) { // TODO: updateOrientation() } + if (shouldReconfigureZoomGesture) { + updateZoomGesture() + } } catch (e: Throwable) { Log.e(TAG, "update() threw: ${e.message}") invokeOnError(e) @@ -249,4 +252,22 @@ class CameraView(context: Context) : FrameLayout(context) { cameraSession.setTorchMode(torch == Torch.ON) } } + + @SuppressLint("ClickableViewAccessibility") + private fun updateZoomGesture() { + if (enableZoomGesture) { + val scaleGestureDetector = ScaleGestureDetector(context, object: ScaleGestureDetector.SimpleOnScaleGestureListener() { + override fun onScale(detector: ScaleGestureDetector): Boolean { + zoom *= detector.scaleFactor + cameraSession.setZoom(zoom) + return true + } + }) + setOnTouchListener { _, event -> + scaleGestureDetector.onTouchEvent(event) + } + } else { + setOnTouchListener(null) + } + } } diff --git a/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt b/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt index dd26eba..12e3565 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt @@ -87,6 +87,13 @@ class CameraViewManager : ViewGroupManager() { view.enableDepthData = enableDepthData } + @ReactProp(name = "enableZoomGesture") + fun setEnableZoomGesture(view: CameraView, enableZoomGesture: Boolean) { + if (view.enableZoomGesture != enableZoomGesture) + addChangedPropToTransaction(view, "enableZoomGesture") + view.enableZoomGesture = enableZoomGesture + } + @ReactProp(name = "videoStabilizationMode") fun setVideoStabilizationMode(view: CameraView, videoStabilizationMode: String?) { val newMode = VideoStabilizationMode.fromUnionValue(videoStabilizationMode)