How to mirror the PreviewView in CameraX?

♀尐吖头ヾ 提交于 2021-01-24 14:39:05

问题


Disclaimer: I'm aware of the existence of this question, but it currently stands unresolved and I'm trying to provide extra information without polluting that one with useless answers that won't solve the problem anyway.

I have a custom device with a front camera that is mirrored by default, so I want to display the preview normally and I need to horizontally flip the content of PreviewView, but I'm stuck. Other people in the past have suggested using PreviewView#setScaleX(-1) but it either doesn't work at all or it needs to be called at a very specific point in the code, which I haven't found yet.

The code below is a simplified version of CameraFragment.kt in the official CameraXBasic example; I've added comments where I've already tired calling viewFinder.scaleX = -1f with no success. Honestly I don't really think that the place makes a difference because if I call it with any value other than 1 it works fine with both scaleX and scaleY, but it always ignores the negative sign so it never flips.

private lateinit var viewFinder: PreviewView

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    ...
    viewFinder = view.findViewById(R.id.view_finder)
    // HERE
    viewFinder.post {
        // HERE
        setupCamera()
    }
}

private fun setupCamera() {
    val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
    cameraProviderFuture.addListener(Runnable {
        val cameraProvider = cameraProviderFuture.get()

        val cameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
            .build()

       val preview = Preview.Builder()
            .build()
            .also {
                // HERE
                it.setSurfaceProvider(viewFinder.surfaceProvider)
            }

       cameraProvider.unbindAll()

        try {
            cameraProvider.bindToLifecycle(this, cameraSelector, preview)
            // HERE
        } catch (exc: Exception) {
            Log.e(TAG, "Use case binding failed", exc)
        }
        // HERE
    }, ContextCompat.getMainExecutor(requireContext()))
    // HERE
}

回答1:


Depending on the implementation type (COMPATIBLE vs PERFORMANCE) and the device, PreviewView can either use a TextureView or a SurfaceView, in your case I'm assuming PreviewView is using a SurfaceView, you can confirm this by getting access to PreviewView's first child view (View.getChildAt(0)).

TextureView is just like any other View, which is why when PreviewView uses it, setting its scaleX to -1 should mirror the displayed preview. You can call PreviewView.setScaleX(-1F) once the layout is created (e.g. In onViewCreated()).

With SurfaceView, it's a bit tricky, as the Surface and the View are independent in some aspects: The Surface is placed behind the window that holds the View, and the View hierarchy handles correctly composing the entire layout by punching a hole in the window in order to display SurfaceView's Surface. This might explain why mirroring the content SurfaceView displays isn't possible, though I'm not sure why zooming in (scaleX set to values > 1) and out (scaleX set to values between 0 and 1) work nonetheless.



来源:https://stackoverflow.com/questions/65577507/how-to-mirror-the-previewview-in-camerax

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!