可以看到,相机预览拉伸严重,水杯都被拉伸很细长。
因为预览的控件(SurfaceView) 和相机输出的图像,宽高比不一致导致。我们需要统一控件的宽高比和相机输出的宽高比。
自定义一个SurfaceView,根据给定的宽高比,进行设置自身的宽高。
public class AutoFitSurfaceView extends SurfaceView {
private float mAspectRatio;
public AutoFitSurfaceView(Context context) {
super(context);
}
public AutoFitSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoFitSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setAspectRatio(int width,int height){
mAspectRatio = (float)width / height;
getHolder().setFixedSize(width,height);
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (mAspectRatio == 0) {
setMeasuredDimension(width,height);
}else {
int newW,newH;
float actualRatio;
if (width > height) {
actualRatio = mAspectRatio;
}else {
actualRatio = 1/ mAspectRatio;
}
if (width < height * actualRatio){
newH = height;
newW = (int) (height * actualRatio);
}else {
newW = width;
newH = (int) (width /actualRatio);
}
setMeasuredDimension(newW,newH);
}
}
}
增加SurfaceView 创建的监听,拿到相机支持输出的宽高,计算合适的宽高,设置给自定义的SurfaceView.
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d("CameraFragment", "surfaceCreated");
mSupportSize = CameraUtils.getSupportSize(mRoot, 0, 0, mCamera.getParameters().getSupportedPreviewSizes());
mSurfaceView.setAspectRatio(mSupportSize.width, mSupportSize.height);
mRoot.post(new Runnable() {
@Override
public void run() {
initCamera(mSurfaceView);
}
});
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("CameraFragment", "surfaceDestroyed");
}
});
public static Camera.Size getSupportSize(View view, int width, int height, List allSize){
Display display = view.getDisplay();
Point point = new Point();
display.getSize(point);
for (Camera.Size size : allSize) {
if (size.width <= point.y && size.height <= point.x) {
return size;
}
}
return allSize.get(0);
}
初始化相机的时候,指定相机预览的宽高为上一步设置的宽高。
private void initCamera(AutoFitSurfaceView surfaceView) {
try {
mCamera.setPreviewDisplay(surfaceView.getHolder());
mCamera.setAutoFocusMoveCallback(new Camera.AutoFocusMoveCallback() {
@Override
public void onAutoFocusMoving(boolean start, Camera camera) {
Log.d("CameraFragment", "onAutoFocusMoving start:" + start);
}
});
mCamera.setDisplayOrientation(90);
Camera.Parameters parameters = mCamera.getParameters();
// 拿到支持的输出分辨率 这个分辨率好像是横屏*竖屏 比如 1920*1080
List supportedPreviewSizes = parameters.getSupportedPreviewSizes();
//设置输出的分辨率
parameters.setPreviewSize(mSupportSize.width, mSupportSize.height);
//持续对焦模式 这种模式下不能调用autoFocus
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
parameters.setJpegQuality(100);
//设置拍照的格式
parameters.setPictureFormat(ImageFormat.JPEG);
//设置拍照的分辨率
parameters.setPictureSize(mSupportSize.width, mSupportSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();