显示相机预览内容是每个相机类应用都会包含的功能,想要完美实现这个却并非易事。原因是,在某些特别极端情况下 camera2 API 的使用会变得很复杂,而且在不同设备上的行为还会有所不同。还好,Jetpack CameraX 库的 PreviewView 可以帮助您解决这一问题。通过在各种 Android 设备上提供开发者友好、一致且稳定的 API,使得展示相机的预览变得不再困难。
PreviewView 的介绍
PreviewView 是一个可以显示相机画面的自定义 View,它被构建的初衷便是降低开发者们在设置和处理相机所使用的预览画面 (preview surface) 的难度。
如果您需要在应用中提供展示相机画面的基本功能,使用 PreviewView 是最推荐的做法,它有以下几个优点:
- 使用简单: PreviewView 是一个 View,它通过管理 Preview 用例所使用的 Surface 来实现将相机捕捉到的画面展示在界面布局中的全部功能;
- 代码轻量: PreviewView 只专注于实现相机画面预览功能。它所有内部资源都致力于对相机预览画面的展示,以及在相机使用过程中对预览画面 (preview surface) 进行管理。这样的关注点分离使得 PreviewView 的代码能够保持简洁;
- 支持全面: PreviewView 解决了在屏幕上展示相机画面过程中最难处理的部分,包括对画面宽高比、缩放和旋转的处理。不同的设备会导致不一致的行为,包括设备、屏幕尺寸、摄像头硬件支持水平,还会需要适配诸如分屏模式、不同锁定方向和可动态调节尺寸的展示窗口等显示模式,为了解决这些问题并在多种设备上提供无缝体验,PreviewView 还做了一些兼容性的处理。
PreviewView 的实现模式
PreviewView 是 FrameLayout 的子类,它会使用 SurfaceView 或者TextureView 展示来自相机捕捉到的画面。一旦相机准备好,就会创建一个预览画面 (preview surface) 的实例,并在相机使用过程中尽量持有该实例,如果相机还在工作中却提前释放了所持有的预览画面 (preview surface) 实例,就会重新创建一个。
当涉及到诸如功耗和响应时间这些关键指标时,SurfaceView 的表现一般都比 TextureView 要好,这也是为什么 PreviewView 会将 SurfaceView 作为默认实现模式的原因。然而,一些设备 (主要是一些旧版设备) 会在预览画面 (preview surface) 过早释放时出现闪退的情况。可惜的是,使用 SurfaceView 时无法控制何时对画面 (surface) 进行释放,因为这是由 View 层级结构所控制的。因此在这些设备上,PreviewView 只能使用 TextureView 作为实现模式。另外在需要对相机预览界面进行旋转、改变透明度或加入动画的情况下,您也应该强制 PreviewView 使用 TextureView 作为实现模式。
您可以通过调用Prev