问题描述
我正在为 Android 应用程序制作像SnapChat"这样的自定义相机,但相机预览在少数设备(如(Moto g 第二代,one+ one)上拉伸)而不是(Samsung s3,Samsung s4).我使用了以下参考 .
I am making custom Camera like "SnapChat" for a Android app but camera preview is stretched on Few devices like(Moto g second generation , one+ one) but not on(Samsung s3, Samsung s4). I have use the following reference Camera display / preview in full screen does not maintain aspect ratio - image is skewed, stretched in order to fit on the screen. But this does not help me 100%. I am sharing the screen .
Stretched image on Samsung Moto G second generation is .
Samsung S3 images which does not stretched is Above
private void setPreviewLayout() {
if (null == mCamera) {
return;
}
Camera.Parameters parameters = null;
Camera.Size size = null;
try {
int screenWidth = (int) getResources().getDisplayMetrics().widthPixels;
int screenHeight = (int) getResources().getDisplayMetrics().heightPixels;
parameters = mCamera.getParameters();
size = getOptimalPreviewSize(mCamera.getParameters().getSupportedPreviewSizes(), screenWidth, screenHeight);
if (size != null) {
parameters.setPreviewSize(size.width, size.height);
}
parameters.setPictureSize(screenHeight, screenWidth);
;
mCamera.setParameters(parameters);
if (on && currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
} else {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
parameters.setExposureCompensation(0);
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setJpegQuality(100);
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
mCamera.setParameters(parameters);
/*
* camera.setPreviewDisplay(surfaceHolder); camera.startPreview();
*/
} catch (Exception e) {
e.printStackTrace();
}
}
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;
}
Using getOptimalPreviewSize()
is important, but it does not resolve all stretching on all devices in all layouts. You must be prepared to crop the preview a little bit so that the preview fills the screen without distortion.
There are different techniques to force the size of the surface different from the actual screen size, but this one I find the easiest:
I add the CameraView
to my layout:
public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
public CameraView(Context context, AttributeSet attr) {
super(context, attr);
// install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
getHolder().addCallback(this);
}
@Override public void surfaceCreated(SurfaceHolder holder) {
openCamera();
bCameraInitialized = false;
}
@Override public void surfaceDestroyed(SurfaceHolder holder) {
camera.release();
}
@Override public void surfaceChanged(SurfaceHolder holder,
int format, int w, int h) {
if (bCameraInitialized) {
// we will get here after we have resized the surface, see below
return;
}
cameraSetup(w, h);
bCameraInitialized = true;
}
private void cameraSetup(int w, int h) {
// set the camera parameters, including the preview size
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
double cameraAspectRatio = ((double)optimalSize.width)/optimalSize.height;
if (((double)h)/w > cameraAspectRatio) {
lp.width = (int)(h/cameraAspectRatio+0.5);
lp.height = h;
}
else {
lp.height = (int)(w*cameraAspectRatio + 0.5);
lp.width = w;
lp.topMargin = (h - lp.height)/2;
}
lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
setLayoutParams(lp);
requestLayout();
}
To emphasize the main idea, I did not include error handling, and I did not show here how the camera is actually started with a secondary Looper.
这篇关于在少数 Android 设备上扩展了相机预览的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!