如何在 Android 中冻结 cameraX 预览?
how can I freeze cameraX preview in Android?
我想让相机在按下图像捕捉按钮时冻结预览。我看过其他堆栈溢出问题,但它们已经过时了。
我使用的cameraX版本:1.0.0-beta03
如有任何帮助,我们将不胜感激。谢谢
目前还没有“正确”的方法来做到这一点,但有几种方法可以实现它,包括:
通过取消绑定 Preview
用例停止预览流,拍照,然后绑定 new Preview
用例继续预览流。
要使这种方法起作用,您还需要绑定一个 ImageAnalysis
用例,因为 ImageCapture
如果它是唯一绑定的用例(另一个 Preview
或 ImageAnalysis
用例也必须绑定,查看官方文档the possible use case combinations)。虽然这种方法有效,但会导致调用 ImageCapture
回调和继续预览之间的轻微延迟,在此期间屏幕将是空白的。
拍照时,使用ImageAnalysis
的最新帧显示在预览之上,你可以转换帧-这是一个ImageProxy
- 到 Bitmap
并显示在 ImageView
中。调用 ImageCapture
回调后,移除框架并继续预览。
编辑:
从相机视图版本 1.0.0-alpha12 开始,您可以使用 PreviewView.getBitmap()
获得预览的 Bitmap
表示。使用此方法,您可以在用户拍照时获取预览的 Bitmap
表示,以 ImageView
的形式显示在预览的顶部,然后一旦图像捕获结果可用,隐藏图像。
此外,我认为您可以尝试创建(作为解决方法)自定义 LifecycleOwner 包装器,并在您想暂停预览时手动将生命周期状态设置为 ON_PAUSE。所以它会是这样的:
class CameraXLifecycleOwner : LifecycleOwner {
private val lifecycle = LifecycleRegistry(this)
private val observer = object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreate() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
}
}
fun attachLifecycleOwner(lifecycleOwner: LifecycleOwner) {
lifecycle.currentState = lifecycleOwner.lifecycle.currentState
lifecycleOwner.lifecycle.addObserver(observer)
}
fun detachLifecycleOwner(lifecycleOwner: LifecycleOwner) {
lifecycleOwner.lifecycle.removeObserver(observer)
}
fun pauseCamera() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
}
fun resumeCamera() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
override fun getLifecycle(): Lifecycle = lifecycle
}
因此,您然后通过将默认片段的 viewLifecycleOwner 传递给 attachLifecycleOwner() 来包装它,这样包装器将重复所有 viewLifecycleOwner 的状态,但是您也可以调用 pauseCamera()/resumeCamera() 来手动更改状态伪造 onPause/onResume 状态改变。不确定这是不是最好的主意,但这是一个主意。
我想让相机在按下图像捕捉按钮时冻结预览。我看过其他堆栈溢出问题,但它们已经过时了。
我使用的cameraX版本:1.0.0-beta03
如有任何帮助,我们将不胜感激。谢谢
目前还没有“正确”的方法来做到这一点,但有几种方法可以实现它,包括:
通过取消绑定
Preview
用例停止预览流,拍照,然后绑定 newPreview
用例继续预览流。 要使这种方法起作用,您还需要绑定一个ImageAnalysis
用例,因为ImageCapture
如果它是唯一绑定的用例(另一个Preview
或ImageAnalysis
用例也必须绑定,查看官方文档the possible use case combinations)。虽然这种方法有效,但会导致调用ImageCapture
回调和继续预览之间的轻微延迟,在此期间屏幕将是空白的。拍照时,使用
ImageAnalysis
的最新帧显示在预览之上,你可以转换帧-这是一个ImageProxy
- 到Bitmap
并显示在ImageView
中。调用ImageCapture
回调后,移除框架并继续预览。
编辑:
从相机视图版本 1.0.0-alpha12 开始,您可以使用 PreviewView.getBitmap()
获得预览的 Bitmap
表示。使用此方法,您可以在用户拍照时获取预览的 Bitmap
表示,以 ImageView
的形式显示在预览的顶部,然后一旦图像捕获结果可用,隐藏图像。
此外,我认为您可以尝试创建(作为解决方法)自定义 LifecycleOwner 包装器,并在您想暂停预览时手动将生命周期状态设置为 ON_PAUSE。所以它会是这样的:
class CameraXLifecycleOwner : LifecycleOwner {
private val lifecycle = LifecycleRegistry(this)
private val observer = object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreate() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
}
}
fun attachLifecycleOwner(lifecycleOwner: LifecycleOwner) {
lifecycle.currentState = lifecycleOwner.lifecycle.currentState
lifecycleOwner.lifecycle.addObserver(observer)
}
fun detachLifecycleOwner(lifecycleOwner: LifecycleOwner) {
lifecycleOwner.lifecycle.removeObserver(observer)
}
fun pauseCamera() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
}
fun resumeCamera() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
override fun getLifecycle(): Lifecycle = lifecycle
}
因此,您然后通过将默认片段的 viewLifecycleOwner 传递给 attachLifecycleOwner() 来包装它,这样包装器将重复所有 viewLifecycleOwner 的状态,但是您也可以调用 pauseCamera()/resumeCamera() 来手动更改状态伪造 onPause/onResume 状态改变。不确定这是不是最好的主意,但这是一个主意。