Android 相機(jī)打開預(yù)覽后,可能存在旋轉(zhuǎn)90/180/270度的問題,也會(huì)影我們計(jì)算預(yù)覽尺寸,應(yīng)該怎么處理呢?
由于大部分手機(jī)都是旋轉(zhuǎn)了90度,導(dǎo)致很多開發(fā)者直接把預(yù)覽畫面轉(zhuǎn)90度回去,出現(xiàn)兼容問題,這是不對(duì)的。
預(yù)覽角度旋轉(zhuǎn)的原因:
(1) 攝像頭傳感器在安裝時(shí)就和屏幕豎直方向存在夾角(orientation),大部分手機(jī)為90度;
(2) 手機(jī)會(huì)橫豎屏切換,導(dǎo)致手機(jī)屏幕的上方向和手機(jī)物理的上方向也有一個(gè)角度(rotation)。
下面我們看如何恢復(fù)畫面的預(yù)覽:
1. 獲取相機(jī)傳感器的安裝角度
安裝角度是指手機(jī)自然狀態(tài)下的上方向與攝像頭的上方向的夾角,方向是從攝像頭的上方向逆時(shí)針旋轉(zhuǎn)到手機(jī)的上方向。

orientation
Camera1:
fun getCameraOrientation(cameraID: Int): Int {
val info = new Camera.CameraInfo()
Camera.getCameraInfo(cameraID, info)
return info.orientation
}
Camera2:
fun getCameraOrientation(context: Context, cameraID: Int): Int {
val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
// 獲取該相機(jī)的特征
val properties = manager.getCameraCharacteristics(cameraID)
// 獲取相機(jī)配置
val config = properties.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
// 獲取旋轉(zhuǎn)角度
return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)
}
2. 獲取手機(jī)屏幕的角度
屏幕的角度是指手機(jī)自然狀態(tài)下的上方向與當(dāng)前畫面上方向的夾角。方向是從畫面上方向逆時(shí)針旋轉(zhuǎn)到手機(jī)上方向。

rotation
fun displayRotation(context: Context): Int {
return when(context.windowManager.defaultDisplay.rotation) {
Surface.ROTATION_0 -> 0
Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270
else -> 0
}
}
3. 計(jì)算恢復(fù)角度
通過兩個(gè)角度的定義,我們很容易知道怎么旋轉(zhuǎn)可以把畫面恢復(fù):
val angle = (orientation - rotation + 360) % 360
4. 使用恢復(fù)角度
- 用于矯正 Camera1 的預(yù)覽角度:
camera.setDisplayOrientation(angle)
- 用于矯正 Camera1 的照片保存角度:
Camera1 通過設(shè)置 Parameters 矯正照片保存角度:
val camera: Camera = ...
val params = camera.getParameters()
params.setRotation(angle)
camera.setParameters(params)
- 用于矯正 Camera2 的照片保存角度:
Camera2 在創(chuàng)建 CaptureRequest 時(shí)設(shè)置照片保存角度:
val builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
builder.set(CaptureRequest.JPEG_ORIENTATION, angle)
Camera2 在預(yù)覽時(shí)會(huì)自動(dòng)矯正預(yù)覽角度。
在挑選預(yù)覽畫面尺寸時(shí),也是需要用到這個(gè)角度的。