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