为什么 View.display 返回 null?

2023-12-19

我正在尝试使用本教程来实现 CameraX:https://codelabs.developers.google.com/codelabs/camerax-getting-started/#5 https://codelabs.developers.google.com/codelabs/camerax-getting-started/#5我的应用程序有一个活动、导航主机和两个片段。我还在我的片段上使用数据绑定。当我尝试旋转显示时,出现错误。

这是我的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="viewModel"
            type="com.ayonix.faceticket.camerapreview.CameraPreviewViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".camerapreview.CameraPreviewFragment">

        <TextureView
            android:id="@+id/camera_preview"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="9:16"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

这是我的片段代码:

class CameraPreviewFragment : Fragment() {

    private lateinit var binding: CameraPreviewFragmentBinding
    private lateinit var viewModel: CameraPreviewViewModel

    private val previewConfig = PreviewConfig.Builder().build()
    private val preview = Preview(previewConfig)

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = CameraPreviewFragmentBinding.inflate(inflater, container, false)
        binding.lifecycleOwner = this

        val viewModelFactory = CameraPreviewViewModelFactory((activity as MainActivity).faceIDUtils)
        viewModel = ViewModelProviders.of(this, viewModelFactory).get(CameraPreviewViewModel::class.java)
        binding.viewModel = viewModel

        startCamera()

        return binding.root
    }

    private fun startCamera() {
        preview.setOnPreviewOutputUpdateListener {
            val parent = binding.cameraPreview.parent as ViewGroup
            parent.removeView(binding.cameraPreview)
            parent.addView(binding.cameraPreview, 0)

            binding.cameraPreview.surfaceTexture = it.surfaceTexture
            updateTransform()
        }

        CameraX.bindToLifecycle(this, preview, viewModel.analyzerUseCase)
    }

    private fun updateTransform() {
        val matrix = Matrix()

        val centerX = binding.cameraPreview.width / 2f
        val centerY = binding.cameraPreview.height / 2f

        val rotationDegrees = when(binding.cameraPreview.display.rotation) {
            Surface.ROTATION_0 -> 0
            Surface.ROTATION_90 -> 90
            Surface.ROTATION_180 -> 180
            Surface.ROTATION_270 -> 270
            else -> return
        }
        matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)

        binding.cameraPreview.setTransform(matrix)
    }

}

我尝试过像这样旋转binding.root.display.rotation。但它也给出了同样的错误。

这是错误:java.lang.IllegalStateException: binding.cameraPreview.display must not be null


3个月后我找到了原因。 startCamera() 必须在 onViewCreated 中调用。除了膨胀布局之外,您不应该在 onCreateView() 中执行任何操作。固定代码是这样的:

class CameraPreviewFragment : Fragment() {

    private lateinit var binding: CameraPreviewFragmentBinding
    private lateinit var viewModel: CameraPreviewViewModel

    private val previewConfig = PreviewConfig.Builder().build()
    private val preview = Preview(previewConfig)

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = CameraPreviewFragmentBinding.inflate(inflater, container, false)
        binding.lifecycleOwner = this

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val viewModelFactory = CameraPreviewViewModelFactory((activity as MainActivity).faceIDUtils)
        viewModel =
            ViewModelProviders.of(this, viewModelFactory).get(CameraPreviewViewModel::class.java)
        binding.viewModel = viewModel

        startCamera()
    }

    private fun startCamera() {
        preview.setOnPreviewOutputUpdateListener {
            val parent = binding.cameraPreview.parent as ViewGroup
            parent.removeView(binding.cameraPreview)
            parent.addView(binding.cameraPreview, 0)

            binding.cameraPreview.surfaceTexture = it.surfaceTexture
            updateTransform()
        }

        CameraX.bindToLifecycle(this, preview, viewModel.analyzerUseCase)
    }

    private fun updateTransform() {
        val matrix = Matrix()

        val centerX = binding.cameraPreview.width / 2f
        val centerY = binding.cameraPreview.height / 2f

        val rotationDegrees = when (binding.cameraPreview.display.rotation) {
            Surface.ROTATION_0 -> 0
            Surface.ROTATION_90 -> 90
            Surface.ROTATION_180 -> 180
            Surface.ROTATION_270 -> 270
            else -> return
        }
        matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)

        binding.cameraPreview.setTransform(matrix)
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 View.display 返回 null? 的相关文章

随机推荐