4. 预览目标旋转角处理

预览目标旋转角处理 学习卡片

为什么预览方向会“歪”

CameraX 的 Preview 默认会依据设备自然方向(natural orientation)和传感器方向自动计算旋转,但当你把界面锁定为竖屏、或 Activity 被系统重建、或使用自定义 PreviewView 容器时,自动结果可能与用户看到的画面方向不一致。此时需要显式设置 Preview.targetRotation,把“显示方向”的期望值告诉 CameraX。

关键概念:targetRotation 不是“旋转多少度”,而是“期望的显示方向”,取值来自 Surface.ROTATION_0 / 90 / 180 / 270,CameraX 会结合传感器方向换算出实际旋转量。

设备物理旋转 → targetRotation 取值 → 预览显示方向 设备姿态 竖屏 ROTATION_0 横屏(左转) ROTATION_90 倒竖屏 ROTATION_180 横屏(右转) ROTATION_270 设置 Preview.targetRotation preview.targetRotation = display.rotation 或固定 ROTATION_0 CameraX 结合 sensorOrientation 换算 实际旋转角度 输出 PreviewView 显示 画面方向正确 人像/景物不歪斜 旋转后仍正确 Activity 重建后 方向保持一致

配置 targetRotation 的两种策略

策略一:跟随系统显示方向。适用于大多数普通预览场景,让预览始终与用户手持方向一致。

// 在绑定 Preview 之前或之后均可设置
val preview = Preview.Builder().build()
preview.targetRotation = display.rotation  // display 来自 Activity 的 windowManager

// 若使用 PreviewView,也可通过其 display 获取
previewView.display?.let { preview.targetRotation = it.rotation }

策略二:固定方向。适用于界面锁定竖屏、或需要预览始终以某个方向呈现的场景。

// 强制预览始终为竖屏方向
preview.targetRotation = Surface.ROTATION_0

在 Activity 方向变化时同步更新

当 Activity 因旋转被重建时,display.rotation 会变化,需要在重建后重新赋值。若使用 android:configChanges 避免重建,则需在 onConfigurationChanged 中手动更新。

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    val rotation = display.rotation
    preview.targetRotation = rotation
}
若使用 CameraX 的 CameraController(PreviewView 的简化封装),它内部已自动处理 targetRotation,无需手动设置。本案例针对直接使用 Preview UseCase 的场景。

验证旋转后的显示效果

  1. 启动应用,确认竖屏下预览画面中的人像/景物方向正常,无 90° 歪斜。
  2. 将设备顺时针旋转 90° 进入横屏,观察预览画面是否随之旋转并保持正确方向。
  3. 若 Activity 被重建,检查重建后预览是否仍然方向正确;若未重建,检查 onConfigurationChanged 是否生效。
  4. 将设备倒置(180°),确认预览方向是否跟随;若固定为 ROTATION_0,则画面应保持竖屏方向不变。
常见问题:设置 targetRotation 后画面仍歪斜,通常是因为 PreviewView 的 scaleType 或父容器布局导致裁剪,而非旋转角错误。可先确认 targetRotation 是否与 display.rotation 一致,再排查布局。

快速检查表

检查项预期异常处理
竖屏下预览方向人像正立检查 targetRotation 是否为 ROTATION_0
横屏旋转后画面跟随旋转确认 display.rotation 已更新并重新赋值
Activity 重建后方向保持正确在 onCreate 中重新设置 targetRotation
固定方向场景画面不随设备旋转确认 targetRotation 未被其他代码覆盖