我一直致力于在 Android 上制作我的自定义相机 Activity ,但是当旋转相机时,表面 View 的纵横比会变得困惑。
在我的 oncreate Activity 中,我设置了 framelayout,它包含显示相机参数的表面 View 。
//FrameLayout that will hold the camera preview
FrameLayout previewHolder = (FrameLayout) findViewById(R.id.camerapreview);
//Setting camera's preview size to the best preview size
Size optimalSize = null;
camera = getCameraInstance();
double aspectRatio = 0;
if(camera != null){
//Setting the camera's aspect ratio
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
optimalSize = CameraPreview.getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
aspectRatio = (float)optimalSize.width/optimalSize.height;
}
if(optimalSize!= null){
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int)(getResources().getDisplayMetrics().widthPixels*aspectRatio));
previewHolder.setLayoutParams(params);
LayoutParams surfaceParams = new LayoutParams(LayoutParams.MATCH_PARENT, (int)(getResources().getDisplayMetrics().widthPixels*aspectRatio));
cameraPreview.setLayoutParams(surfaceParams);
}
cameraPreview.setCamera(camera);
//Adding the preview to the holder
previewHolder.addView(cameraPreview);
然后,在 Surface View 中,我设置要显示的相机参数
public void setCamera(Camera camera) {
if (mCamera == camera) { return; }
mCamera = camera;
if (mCamera != null) {
requestLayout();
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
e.printStackTrace();
}
if(mCamera != null){
//Setting the camera's aspect ratio
Camera.Parameters parameters = mCamera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setParameters(parameters);
}
/*
Important: Call startPreview() to start updating the preview surface. Preview must
be started before you can take a picture.
*/
mCamera.startPreview();
}
}
你可以看到,当手机旋转时,乐高人变得又高又瘦:
如何确保相机 View 的纵横比正确?
最佳答案
我正在使用这种方法 -> 基于 API Demos 来获取我的预览大小:
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
如您所见,您必须输入屏幕的宽度和高度。此方法将根据这些值计算屏幕比例,然后从supportedPreviewSizes 列表中选择最适合您的可用值。使用
将您的 supportedPreviewSize 列表放在 Camera 对象不为空的位置mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
然后在 onMeasure 中,您可以像这样获得最佳 previewSize:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
然后(在我的surfaceChanged方法的代码中,就像我说的我使用CameraActivity代码的API Demos结构,你可以在Eclipse中生成它):
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
给你一个提示,因为我做了几乎和你一样的应用程序。 Camera Activity 的良好做法是隐藏 StatusBar。 Instagram 等应用程序正在这样做。它会降低您的屏幕高度值并更改您的比率值。在某些设备上可能会出现奇怪的预览尺寸(你的 SurfaceView 会被剪掉一点)
为了回答您的问题,如何检查您的预览比例是否正确?然后获取您设置的参数的高度和宽度:
mCamera.setParameters(parameters);
您的设定比例等于高度/宽度。如果您希望相机在屏幕上看起来不错,那么您为相机设置的参数的高宽比必须与屏幕的高(减去状态栏)/宽比相同。
关于Android 相机预览已拉伸(stretch),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19577299/