问题描述
免责声明:我知道 this question 的存在,但它目前尚未解决,我正在尝试提供额外的信息,而不会用无法解决问题的无用答案污染那个信息无论如何。
我有一个带有前置摄像头的自定义设备,默认情况下是镜像的,所以我想正常显示预览,我需要水平翻转PreviewView的内容,但我卡住了。过去其他人曾建议使用 PreviewView#setScaleX(-1)
,但它要么根本不起作用,要么需要在代码中非常特定的位置调用,而我还没有找到。
下面的代码是官方CameraXBasic示例中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
}
解决方法
根据实现类型(COMPATIBLE
与 PERFORMANCE
)和设备,PreviewView
可以使用 TextureView
或 SurfaceView
,在您的情况下我假设 PreviewView
正在使用 SurfaceView
,您可以通过访问 PreviewView
的第一个子视图 (View.getChildAt(0)
) 来确认这一点。
TextureView
就像任何其他 View
一样,这就是为什么当 PreviewView
使用它时,将其 scaleX 设置为 -1 应该反映显示的预览。创建布局后(例如在 PreviewView.setScaleX(-1F)
中),您可以调用 onViewCreated()
。
对于 SurfaceView
,它有点棘手,因为 Surface
和 View
在某些方面独立:Surface
被放置在包含 View
的窗口后面,View 层次结构通过在窗口中打一个洞来正确处理整个布局,以显示 SurfaceView
的 Surface
。这可能解释了为什么无法镜像内容 SurfaceView
显示,尽管我不确定为什么放大(scaleX 设置为值 > 1)和缩小(scaleX 设置为 0 和 1 之间的值)仍然有效。