2. 预览画面镜像控制

预览画面镜像控制 学习卡片

前置预览镜像的本质

CameraX 的 Preview 默认对前置摄像头做水平镜像,让预览画面像照镜子一样自然。镜像发生在 PreviewView 的显示层,而不是传感器输出层——传感器数据本身没有翻转,翻转只影响用户看到的画面。因此镜像配置只改变"显示效果",不改变分析用的图像数据。

镜像模式由 PreviewView.setScaleType() 之外的 PreviewView.setMirrorMode() 控制,取值来自 PreviewView.MirrorMode:

  • MIRROR_MODE_ON_FRONT_ONLY(默认):仅前置镜像,后置不镜像。
  • MIRROR_MODE_ON:前后置都镜像。
  • MIRROR_MODE_OFF:前后置都不镜像。

关键点:镜像模式是 PreviewView 的属性,与 Preview 用例绑定无关,切换摄像头时无需重新绑定,只需保证 PreviewView 实例不变。

Camera 传感器 原始图像(未翻转) 前置 / 后置 图像流 Preview 用例 绑定到 CameraProvider 不负责镜像 Surface PreviewView setMirrorMode() 显示层水平翻转 用户看到的画面 MirrorMode 取值与效果 ON_FRONT_ONLY 前置:镜像 后置:不镜像 MIRROR_MODE_ON 前置:镜像 后置:镜像 MIRROR_MODE_OFF 前置:不镜像 后置:不镜像

实现镜像控制

在例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 实例。