如何使用 Android CameraX 自动对焦

Blu*_*lue 8 android kotlin android-studio android-camerax

最近几个月,Android 发布了一个新的 API camerax。我试图了解如何让相机自动对焦工作。

https://groups.google.com/a/android.com/forum/#!searchin/camerax-developers/auto $20focus|sort:date/camerax-developers/IQ3KZd8iOIY/LIbrRIqEBgAJ

这是关于该主题的讨论,但几乎没有关于它的具体文档。

https://github.com/android/camera-samples/tree/master/CameraXBasic/app/src/main/java/com/android/example/cameraxbasic

这也是基本的camerax应用程序,但我找不到任何处理自动对焦的文件。

任何有关文档的提示或要点都是有帮助的。另外,我对 android 还很陌生,所以很可能我遗漏了一些使上述链接更有用的东西。

Mat*_*Pag 28

使用当前的 CameraX 1.0.0,您可以通过以下两种方式进行:

  1. 每 X 秒自动对焦:

     previewView.afterMeasured {
         val autoFocusPoint = SurfaceOrientedMeteringPointFactory(1f, 1f)
                 .createPoint(.5f, .5f)
         try {
             val autoFocusAction = FocusMeteringAction.Builder(
                 autoFocusPoint,
                 FocusMeteringAction.FLAG_AF
             ).apply {
                 //start auto-focusing after 2 seconds
                 setAutoCancelDuration(2, TimeUnit.SECONDS)
             }.build()
             camera.cameraControl.startFocusAndMetering(autoFocusAction)
         } catch (e: CameraInfoUnavailableException) {
             Log.d("ERROR", "cannot access camera", e)
         }
     }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 专注于点击:

     previewView.afterMeasured {
         previewView.setOnTouchListener { _, event ->
             return@setOnTouchListener when (event.action) {
                 MotionEvent.ACTION_DOWN -> {
                     true
                 }
                 MotionEvent.ACTION_UP -> {
                     val factory: MeteringPointFactory = SurfaceOrientedMeteringPointFactory(
                         previewView.width.toFloat(), previewView.height.toFloat()
                     )
                     val autoFocusPoint = factory.createPoint(event.x, event.y)
                     try {
                         camera.cameraControl.startFocusAndMetering(
                             FocusMeteringAction.Builder(
                                 autoFocusPoint,
                                 FocusMeteringAction.FLAG_AF
                             ).apply {
                                 //focus only when the user tap the preview
                                 disableAutoCancel()
                             }.build()
                         )
                     } catch (e: CameraInfoUnavailableException) {
                         Log.d("ERROR", "cannot access camera", e)
                     }
                     true
                 }
                 else -> false // Unhandled event.
             }
         }
     }
    
    Run Code Online (Sandbox Code Playgroud)

afterMeasured扩展函数是一个简单的实用程序:

inline fun View.afterMeasured(crossinline block: () -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            if (measuredWidth > 0 && measuredHeight > 0) {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                block()
            }
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

Camera对象可以用获得

val camera = cameraProvider.bindToLifecycle(
    this@Activity, cameraSelector, previewView //this is a PreviewView
)
Run Code Online (Sandbox Code Playgroud)

  • 由于某种原因,这段代码在大多数设备上运行良好,但其他一些设备只是拒绝改变焦点,我找不到原因。 (2认同)
  • 嗨,“afterMeasured”有一个错误:它的回调经常不会被调用。这是一个修复:/sf/answers/4921288151/ (2认同)

小智 5

只是指出,要使“点击焦点”与 PreviewView 配合使用,您需要使用 DisplayOrientedMeteringPointFactory。否则你会弄乱坐标。

val factory = DisplayOrientedMeteringPointFactory(activity.display, camera.cameraInfo, previewView.width.toFloat(), previewView.height.toFloat())
Run Code Online (Sandbox Code Playgroud)

其余的请使用 MatPag 的答案。