Android 如何在CameraX中镜像预览视图?

Android 如何在CameraX中镜像预览视图?,android,android-view,android-camerax,Android,Android View,Android Camerax,免责声明:我知道存在,但它目前尚未解决,我正试图提供额外的信息,而不会用无用的答案污染该信息,而这些答案无论如何也解决不了问题。 我有一个自定义设备,带有默认镜像的前置摄像头,所以我想正常显示预览,需要水平翻转PreviewView的内容,但我卡住了。过去也有人建议使用PreviewView#setScaleX(-1),但它要么根本不起作用,要么需要在代码中的一个非常特定的点调用,我还没有找到 下面的代码是官方示例中的CameraFragment.kt的简化版本;我添加了一些注释,我已经厌倦了调

免责声明:我知道存在,但它目前尚未解决,我正试图提供额外的信息,而不会用无用的答案污染该信息,而这些答案无论如何也解决不了问题。

我有一个自定义设备,带有默认镜像的前置摄像头,所以我想正常显示预览,需要水平翻转PreviewView的内容,但我卡住了。过去也有人建议使用
PreviewView#setScaleX(-1)
,但它要么根本不起作用,要么需要在代码中的一个非常特定的点调用,我还没有找到

下面的代码是官方示例中的
CameraFragment.kt
的简化版本;我添加了一些注释,我已经厌倦了调用
viewFinder.scaleX=-1f
,但没有成功。老实说,我真的不认为这个地方有什么区别,因为如果我用除1以外的任何值调用它,它对
scaleX
scaleY
都很好,但是它总是忽略负号,所以它从不翻转

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
}

根据实现类型(
兼容
vs
性能
)和设备,
预览视图
可以使用
纹理视图
表面视图
,在您的情况下,我假设
预览视图
使用的是
表面视图
,您可以通过访问
PreviewView
的第一个子视图(
view.getChildAt(0)
)来确认这一点

TextureView
与任何其他
View
一样,这就是为什么
PreviewView
使用它时,将其scaleX设置为-1应该镜像显示的预览。创建布局后(例如在
onViewCreated()
中),可以调用
PreviewView.setScaleX(-1F)


使用
SurfaceView
,这有点棘手,因为
Surface
View
在某些方面是独立的:
Surface
放在保存
视图的窗口后面,视图层次结构通过在窗口上打孔来正确组合整个布局,以便显示
SurfaceView
Surface
。这也许可以解释为什么镜像内容
SurfaceView
显示是不可能的,尽管我不确定为什么放大(scaleX设置为值>1)和缩小(scaleX设置为值介于0和1之间)仍然有效。

该设备运行在安卓7.1上,并记录
取景器。getChildAt(0)
显示
空值。
scaleX
被设置为-1并且。。。现在它起作用了吗?但是我刚刚在我自己的手机上用安卓10试用了这个应用程序,尽管预览版还没有翻动,我还是得到了同样的结果。我不知道。你应该在预览开始后调用
getChildAt(0)
。你是说在调用
bindToLifecycle()
之后?仍然得到
null
。否,调用
binToLifecycle()
后预览不会立即启动。您可以使用
PreviewView.getPreviewStreamState()
并等待
流式处理
状态被调度。您也可以使用任何其他方式仅在看到预览开始后调用该方法,例如,在
PreviewView
上设置一个单击侦听器,当您看到预览开始时,单击它,在单击侦听器内您可以记录它的第一个子项。谢谢。令人惊讶的是,在定制设备上默认使用
TextureView
,这可能就是它实际工作的原因,而在我手机上使用的
SurfaceView
仍然不希望协作。需要明确的是,可靠镜像
SurfaceView
的唯一方法是实时将每个帧转换为位图,并将其绘制回曲面上?