androidkotlinandroid-cameraandroid-cameraxpinchzoom

How to implement pinch to zoom and camera preview kotlin


I have a camera I'm trying to create in my app that allows users to pinch the preview screen when using the camera. I've been trying to implement pinch to zoom in my camera, but I am having no luck at all. This is the code I found on a github thread

val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            // Get the current camera zoom ratio
            val currentZoomRatio: Float = cameraInfo.zoomRatio.value ?: 1F

            // Get by how much the scale has changed due to the user's pinch gesture
            val delta = detector.scaleFactor

            // Update the camera's zoom ratio
            cameraControl.setZoomRatio(currentZoomRatio * delta)
            return true
        }
    }

    val scaleGestureDetector = ScaleGestureDetector(requireContext(), listener)
    progressDialog = ProgressDialog(requireContext(), false)
    binding.cameraPreview.post {
        startCamera()
    }
    binding.ivImageCapture.setOnClickListener {
        progressDialog.show()
        takePicture()
    }

    binding.cameraPreview.setOnTouchListener { _, event ->
        scaleGestureDetector.onTouchEvent(event)
        return@setOnTouchListener true
    }
}

The only error I have is "Unresolved reference: zoomRatio". I've upgraded all my dependencies to the latest version.

Here's my startCamera fucntion

@SuppressLint("UnsafeExperimentalUsageError")
private fun startCamera() {
    // Get screen metrics used to setup camera for full screen resolution
    val metrics = DisplayMetrics().also { binding.cameraPreview.display.getRealMetrics(it) }

    val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)

    val rotation = binding.cameraPreview.display.rotation


    // Bind the CameraProvider to the LifeCycleOwner
    val cameraSelector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()
    val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
    cameraProviderFuture.addListener({

        // CameraProvider
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

        // Preview
        val preview = Preview.Builder()
            .setTargetAspectRatio(screenAspectRatio)
            // Set initial target rotation
            .setTargetRotation(rotation)

            .build()

        preview.setSurfaceProvider(binding.cameraPreview.surfaceProvider)

        // ImageCapture
        imageCapture = initializeImageCapture(screenAspectRatio, rotation)

        // ImageAnalysis


        cameraProvider.unbindAll()

        try { val camera = cameraProvider.bindToLifecycle(
            this, cameraSelector, preview, imageCapture
        )
            cameraControl = camera.cameraControl
            cameraInfo = camera.cameraInfo
            cameraControl.setLinearZoom(0.5f)



        } catch (exc: Exception) {
            exc.printStackTrace()
        }
    }, ContextCompat.getMainExecutor(requireContext()))

Solution

  •  // Listen to pinch gestures
        val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
            override fun onScale(detector: ScaleGestureDetector): Boolean {
                // Get the camera's current zoom ratio
                val currentZoomRatio = cameraInfo.zoomState.value?.zoomRatio ?: 0F
    
                // Get the pinch gesture's scaling factor
                val delta = detector.scaleFactor
    
                // Update the camera's zoom ratio. This is an asynchronous operation that returns
                // a ListenableFuture, allowing you to listen to when the operation completes.
                cameraControl.setZoomRatio(currentZoomRatio * delta)
    
                // Return true, as the event was handled
                return true
            }
        }
        val scaleGestureDetector = ScaleGestureDetector(requireContext(), listener)
    
        // Attach the pinch gesture listener to the viewfinder
        binding.cameraPreview.setOnTouchListener { _, event ->
            scaleGestureDetector.onTouchEvent(event)
            return@setOnTouchListener true
        }
    

    This is the source I found it from