2. 预览画面镜像控制
前置预览镜像的本质
CameraX 的 Preview 默认对前置摄像头做水平镜像,让预览画面像照镜子一样自然。镜像发生在 PreviewView 的显示层,而不是传感器输出层——传感器数据本身没有翻转,翻转只影响用户看到的画面。因此镜像配置只改变"显示效果",不改变分析用的图像数据。
镜像模式由 PreviewView.setScaleType() 之外的 PreviewView.setMirrorMode() 控制,取值来自 PreviewView.MirrorMode:
MIRROR_MODE_ON_FRONT_ONLY(默认):仅前置镜像,后置不镜像。MIRROR_MODE_ON:前后置都镜像。MIRROR_MODE_OFF:前后置都不镜像。
关键点:镜像模式是 PreviewView 的属性,与 Preview 用例绑定无关,切换摄像头时无需重新绑定,只需保证 PreviewView 实例不变。
实现镜像控制
在例1的最小预览基础上,只需在 PreviewView 初始化后设置镜像模式。以下代码假设 previewView 已在布局中定义,且相机权限已获取。
// 在 onCreate 或视图初始化后设置
previewView.setMirrorMode(PreviewView.MIRROR_MODE_ON_FRONT_ONLY);
// 绑定相机(与例1一致)
ListenableFuture<ProcessCameraProvider> future = ProcessCameraProvider.getInstance(this);
future.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = future.get();
Preview preview = new Preview.Builder().build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
// 默认绑定后置,镜像模式自动生效
cameraProvider.bindToLifecycle(this, CameraSelector.DEFAULT_BACK_CAMERA, preview);
} catch (Exception e) {
Log.e("CameraX", "绑定失败", e);
}
}, ContextCompat.getMainExecutor(this));
前后置切换与镜像验证
切换摄像头时,PreviewView 实例保持不变,镜像模式自动按当前摄像头方向应用。以下方法演示切换逻辑:
private boolean isFrontCamera = false;
private void switchCamera() {
ProcessCameraProvider cameraProvider = ...; // 已获取的实例
CameraSelector selector = isFrontCamera
? CameraSelector.DEFAULT_BACK_CAMERA
: CameraSelector.DEFAULT_FRONT_CAMERA;
Preview preview = new Preview.Builder().build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
cameraProvider.unbindAll();
cameraProvider.bindToLifecycle(this, selector, preview);
isFrontCamera = !isFrontCamera;
}
验证方法:将
MirrorMode 设为 MIRROR_MODE_ON_FRONT_ONLY,切换到前置时画面应水平翻转(文字反向),切回后置时恢复正常。若设为 MIRROR_MODE_OFF,前置画面文字应正向可读。切换过程中 PreviewView 不重建,镜像状态随摄像头方向自动更新。
常见问题:若在切换时重新创建
PreviewView 或调用 setMirrorMode 的时机晚于绑定,可能出现短暂镜像错误。建议在 bindToLifecycle 之前完成 setMirrorMode 设置,并复用同一个 PreviewView 实例。