简体   繁体   中英

CameraX: How to add pinch to zoom AND tap to focus? onClickListener and onTouchListener

I merged some CameraX tutorials so that it has pinch to zoom and tap to focus. By themselves, they work well, but together, the OnClickListener and OnTouchListeners are interfering with each other.

I thought merging them under a single OnClickListener method where the pinch to zoom is executed on the ACTION_DOWN, and the tap to focus on the ACTION_UP, but only the tap to focus is running. Even if it did work, this feels a bit clunky and I'd appreciate some more advanced guidance.

zoomAndFocus is triggered by: "viewFinder.setOnClickListener{zoomAndFocus()}" in onCreate.

private fun zoomAndFocus(){
    Log.d("onclick","detecting clck?")

    viewFinder.setOnTouchListener { _, event ->

        return@setOnTouchListener when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
                    override fun onScale(detector: ScaleGestureDetector): Boolean {
                        val zoomRatio = camera?.cameraInfo?.zoomState?.value?.zoomRatio ?: 0f
                        val scale = zoomRatio * detector.scaleFactor
                        camera!!.cameraControl.setZoomRatio(scale)
                        return true
                    }
                }

                val scaleGestureDetector = ScaleGestureDetector(this, listener)

                scaleGestureDetector.onTouchEvent(event)


                true
            }
            MotionEvent.ACTION_UP -> {
                val factory: MeteringPointFactory = SurfaceOrientedMeteringPointFactory(
                    viewFinder.width.toFloat(), viewFinder.height.toFloat()
                )
                val autoFocusPoint = factory.createPoint(event.x, event.y)
                try {
                    camera?.cameraControl?.startFocusAndMetering(
                        FocusMeteringAction.Builder(
                            autoFocusPoint,
                            FocusMeteringAction.FLAG_AF
                        ).apply {
                            //focus only when the user tap the preview
                            disableAutoCancel()
                        }.build()
                    )
                } catch (e: CameraInfoUnavailableException) {
                    Log.d("ERROR", "cannot access camera", e)
                }
                viewFinder.performClick()
                true
            }
            else -> false // Unhandled event.
        }

    }

Use this to add pinch to zoom and tap to focus together:

private fun setupZoomAndTapToFocus() {
    val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            val currentZoomRatio: Float = cameraInfo.zoomState.value?.zoomRatio ?: 1F
            val delta = detector.scaleFactor
            cameraControl.setZoomRatio(currentZoomRatio * delta)
            return true
        }
    }

    val scaleGestureDetector = ScaleGestureDetector(viewFinder.context, listener)

    viewFinder.setOnTouchListener { _, event ->
        scaleGestureDetector.onTouchEvent(event)
        if (event.action == MotionEvent.ACTION_DOWN) {
            val factory = viewFinder.createMeteringPointFactory(cameraSelector)
            val point = factory.createPoint(event.x, event.y)
            val action = FocusMeteringAction.Builder(point, FocusMeteringAction.FLAG_AF)
                .setAutoCancelDuration(5, TimeUnit.SECONDS)
                .build()
            cameraControl.startFocusAndMetering(action)
        }
        true
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM