想要一個自定義相機界面:畫面中央顯示一個半透明遮罩框(類似二維碼掃描框),只有框內區域在按下快門後被保存為圖片。
SurfaceView 並實現 SurfaceHolder.Callback,用於顯示相機預覽流。onDraw(Canvas) 中繪製半透明遮罩與中間透明的「掃描框」。預覽畫面與最終拍照圖片的尺寸、比例通常不同,需將框在 SurfaceView 上的座標映射到圖片像素座標:
// 假設掃描框在 SurfaceView 中的矩形為 rectF
float scaleX = (float)pictureWidth / surfaceViewWidth;
float scaleY = (float)pictureHeight / surfaceViewHeight;
int left = (int)(rectF.left * scaleX);
int top = (int)(rectF.top * scaleY);
int right = (int)(rectF.right * scaleX);
int bottom = (int)(rectF.bottom * scaleY);
Camera.PictureCallback jpegCallback = (data, camera) -> {
Bitmap full = BitmapFactory.decodeByteArray(data, 0, data.length);
// 根據相機方向旋轉(關鍵!)
Matrix matrix = new Matrix();
matrix.postRotate(getDisplayOrientation());
Bitmap rotated = Bitmap.createBitmap(full, 0, 0, full.getWidth(), full.getHeight(), matrix, true);
// 裁剪
Bitmap cropped = Bitmap.createBitmap(rotated, left, top, right-left, bottom-top);
// 保存 cropped ...
};
Camera.CameraInfo.orientation 計算正確旋轉角度。CAMERA 權限、onPause/release() 釋放相機資源。Camera2 API;舊版可用 Camera(已棄用但仍可用)。核心在於:自定義預覽 UI 繪製框 → 座標映射 → 拍照回調中旋轉並裁剪 Bitmap。建議直接參考成熟開源庫,避免踩坑。