Android解决SurfaceView预览Camera拉伸问题

搜索了一遍国内的解决方案,基本上都是匹配Camera的支持分辨率,然后直接设置,这个只能解决一部分手机,很多机型仍然显示的时候会出现拉伸,因为Camera支持的分辨率没有刚好适合的当然屏幕尺寸,特别是没有隐藏状态栏,显示的View的尺寸和支持的分辨率不匹配,就出现了图像变形。
以下是我结合分辨率适配以及布局适配,来解决这个问题
在主界面直接在代码里new 一个CustomCameraSurface 对象并Add 进根视图,然后调用OnStart()

import android.app.Activity;import android.content.Context;import android.graphics.PixelFormat;import android.hardware.Camera;import android.util.AttributeSet;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.ViewGroup.LayoutParams;import android.widget.LinearLayout;import android.widget.RelativeLayout;/** * Created by Jackie on 2016/7/26. */public class CustomCameraSurface extends SurfaceView implements SurfaceHolder.Callback {    static private CustomCameraSurface instance;    private LinearLayout frame = null;    private RelativeLayout innerFrame = null;    private Camera camera;    private SurfaceHolder previewHolder;    private boolean inPreview = false;    private boolean cameraConfigured = false;    private Camera.Size size;    static public CustomCameraSurface getInstance(Activity activity) {        if (CustomCameraSurface.instance == null) {            CustomCameraSurface.instance = new CustomCameraSurface(activity);        }        return CustomCameraSurface.instance;    }    public void onStart() {        camera = Camera.open(1);        if (size != null) {            initPreview(size.width, size.height);        }        startPreview();    }    public void onStop() {        if (inPreview && camera != null) {            camera.stopPreview();        }        if (camera != null)            camera.release();        camera = null;        inPreview = false;        setVisibility(GONE);    }    private CustomCameraSurface(Context context) {        super(context);        init();    }    public CustomCameraSurface(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public CustomCameraSurface(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }//初始化    void init() {        previewHolder = getHolder();        previewHolder.addCallback(this);        previewHolder.setFormat(PixelFormat.TRANSPARENT);        innerFrame = new RelativeLayout(getContext());        innerFrame.addView(this);        frame = new LinearLayout(getContext());        frame.addView(innerFrame);    }    public LinearLayout getFrame() {        return frame;    }    public void surfaceChanged(SurfaceHolder holder, int format, int width,                               int height) {        // TODO Auto-generated method stub        initPreview(width, height);        startPreview();    }    public void surfaceCreated(SurfaceHolder holder) {    }    public void surfaceDestroyed(SurfaceHolder holder) {        // 记得销毁,释放相机        onStop();    }    private Camera.Size getBestPreviewSize(int width, int height,                                           Camera.Parameters parameters) {        Camera.Size result = null;        for (Camera.Size size : parameters.getSupportedPreviewSizes()) {            if (size.width <= width && size.height <= height) {                if (result == null) {                    result = size;                } else {                    int resultArea = result.width * result.height;                    int newArea = size.width * size.height;                    if (newArea > resultArea) {                        result = size;                    }                }            }        }        this.size = result;        return (result);    }    private void initPreview(int width, int height) {        //利用布局,重设宽高来撑开界面,超出的部分直接撑出屏幕,至于为什么用这两个布局,自己去谷歌了!        if (camera != null && previewHolder.getSurface() != null) {            if (!cameraConfigured) {                Camera.Parameters parameters = camera.getParameters();                Camera.Size size = getBestPreviewSize(width, height, parameters);                if (size != null) {                    parameters.setPreviewSize(size.width, size.height);                    camera.setParameters(parameters);                    cameraConfigured = true;                    // Setting up correctly the view                    double ratio = size.height / (double) size.width;                    int Y = getResources().getDisplayMetrics().heightPixels;                    int X = getResources().getDisplayMetrics().widthPixels;                    LayoutParams params = innerFrame.getLayoutParams();                    params.height = Y;                    params.width = (int) (Y * ratio);                    innerFrame.setLayoutParams(params);                    int deslocationX = (int) (params.width / 2.0 - X / 2.0);                    innerFrame.animate().translationX(-deslocationX);                }            }            try {                camera.setPreviewDisplay(previewHolder);                camera.setDisplayOrientation(90);            } catch (Throwable t) {            //错误处理,自己做相应的逻辑                setVisibility(GONE);            }        }    }    private void startPreview() {        if (cameraConfigured && camera != null) {            camera.startPreview();            inPreview = true;        }    }}

更多相关文章

  1. 关于 Android(安卓)Fragment的官方说明文档
  2. Android界面布局编程
  3. 第27章、流动视图ScrollView(从零开始学Android)
  4. Android(安卓)改变窗口标题栏的布局
  5. (二)Unity 与 Android的布局管理
  6. .Net码农学Android---五分钟了解布局
  7. Android软件开发之盘点界面五大布局(十六)
  8. 关于Android的屏幕适配
  9. Android的UI组件 .

随机推荐

  1. srand(time(null))函数是什么意思
  2. c语言定义函数
  3. cr是什么意思?
  4. srand(time(0))函数是什么意思
  5. for(;;)什么意思
  6. if是什么意思
  7. 字符串赋值是什么意思
  8. c语言交换两个数的值
  9. remove是什么意思?
  10. 学好c语言要看什么书