1

我写了一个拍照的相机应用程序(活动),但是显示相机实时图片的预览看起来不太好,有点高,像这样: 在此处输入图像描述

这是我的相机预览的代码:

    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
    {
        private SurfaceHolder mHolder ;
        private Camera mCamera; 
        public CameraPreview(Context context , Camera camera)
        {
            super(context) ;
            mCamera = camera ;

            mHolder = getHolder();
            mHolder.addCallback(this);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
        public void surfaceCreated(SurfaceHolder holder)
        {
            try
            {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            }
            catch(IOException e)
            {
                Log.d(TAG,"Camera Preview Failed!: "+e.getMessage());
            }
        }
        public void surfaceChanged(SurfaceHolder holder , int m , int n , int w)
        {   
        }
        public void surfaceDestroyed(SurfaceHolder holder)
        {           
        }
    }



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_width="wrap_content"
        android:layout_height="0dip"
        android:layout_weight="0.86" />

    <Button
        android:id="@+id/button_capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:gravity="center"
        android:onClick="capture"
        android:text="Capture" />

    <Button
        android:id="@+id/button_accept"
        android:layout_width="115dp"
        android:layout_height="wrap_content"
        android:text="Accept"
        android:visibility="gone"
        android:onClick = "accept" />

    <Button
        android:id="@+id/button_retake"
        android:layout_width="107dp"
        android:layout_height="wrap_content"
        android:text="Retake" 
        android:visibility="gone"
        android:onClick = "retake"/>

</LinearLayout>
4

1 回答 1

2
public class IQCameraView extends ViewGroup implements SurfaceHolder.Callback {

public static final int CAMERA_ERROR = 0;
public static final int CAMERA_RESULT = 1;

private final String TAG = "Preview";
private SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
private Size mPreviewSize;
private List<Size> mSupportedPreviewSizes;
private Camera mCamera;

private boolean mCameraActive;

private IQCameraCallback mCallback;

/**
 * @param mCallback
 *            of type IQCameraCallback
 * @return of type null setter function for mCallback
 * @since 10 Oct 2012
 */
public void setmCallback(IQCameraCallback mCallback) {
    this.mCallback = mCallback;
}

/**
 * @param context
 *            of type Context
 * @return of type boolean function which will check the system has a camera
 *         or not
 * @since 10 Oct 2012
 */
public static boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_CAMERA)) {
        return true;
    } else {
        return false;
    }
}

/**
 * @param context
 *            Constructor function
 * @since 16 Oct 2012
 */
public IQCameraView(Context context) {
    super(context);

    mSurfaceView = new SurfaceView(context);
    addView(mSurfaceView);
    mHolder = mSurfaceView.getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

/**
 * @param camera
 *            of type Camera
 * @return of type null setter function for mCamera
 * @since 16 Oct 2012
 */
public void setCamera(Camera camera) {
    mCamera = camera;
    if (mCamera != null) {
        mSupportedPreviewSizes = mCamera.getParameters()
                .getSupportedPreviewSizes();
        requestLayout();
    }
}

/**
 * @param of
 *            type null
 * @return of type null function which will get the current frame from the
 *         camera
 * @since 16 Oct 2012
 */
public void takePicture() {
    if (null != mCamera && mCameraActive) {
        mCamera.takePicture(null, null, new IQPhotoHandler(getContext(),
                this));
    }
}

/**
 * @param result
 *            of type String
 * @return of type null function which will be called when the image save is
 *         complete
 * @since 16 Oct 2012
 */
public void onImageCapture(final String result) {
    if (null != mCallback) {
        mCallback.onCameraCallback(CAMERA_RESULT, result);
    }
    mCamera.startPreview();
}

/*
 * (non-Javadoc)
 * 
 * @see android.view.View#onMeasure(int, int)
 * 
 * @since 16 Oct 2012
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // We purposely disregard child measurements because act as a
    // Wrapper to a SurfaceView that centers the camera preview instead of
    // stretching it.
    final int width = resolveSize(getSuggestedMinimumWidth(),
            widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(),
            heightMeasureSpec);
    setMeasuredDimension(width, height);

    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getPreviewSize(mSupportedPreviewSizes, width, height);
    }
}

/*
 * (non-Javadoc)
 * 
 * @see android.view.ViewGroup#onLayout(boolean, int, int, int, int)
 * 
 * @since 16 Oct 2012
 */
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    if (changed && getChildCount() > 0) {
        final View child = getChildAt(0);

        final int width = r - l;
        final int height = b - t;

        int previewWidth = width;
        int previewHeight = height;

        // Center the child SurfaceView within the parent.
        if (width * previewHeight > height * previewWidth) {
            final int scaledChildWidth = previewWidth * height
                    / previewHeight;
            child.layout((width - scaledChildWidth) / 2, 0,
                    (width + scaledChildWidth) / 2, height);
        } else {
            final int scaledChildHeight = previewHeight * width
                    / previewWidth;
            child.layout(0, (height - scaledChildHeight) / 2, width,
                    (height + scaledChildHeight) / 2);
        }
    }
}

/**
 * @param of
 *            type null
 * @return of type null function which will release teh camera
 * @since 16 Oct 2012
 */
public void releaseCamera() {
    if (null != mCamera && mCameraActive) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
    mCameraActive = false;
}

/*
 * (non-Javadoc)
 * 
 * @see
 * android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder
 * )
 * 
 * @since 16 Oct 2012
 */
public void surfaceCreated(SurfaceHolder holder) {
    try {
        if (mCamera != null) {
            mCamera.setPreviewDisplay(holder);
        }
    } catch (IOException e) {
        Log.e(TAG, "IOException caused by setPreviewDisplay()", e);
    }
}

/*
 * (non-Javadoc)
 * 
 * @see android.view.SurfaceHolder.Callback#surfaceDestroyed(android.view.
 * SurfaceHolder)
 * 
 * @since 16 Oct 2012
 */
public void surfaceDestroyed(SurfaceHolder holder) {
    releaseCamera();
}

/*
 * (non-Javadoc)
 * 
 * @see
 * android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder
 * , int, int, int)
 * 
 * @since 16 Oct 2012
 */
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    parameters.setPictureSize(mPreviewSize.width, mPreviewSize.height);
    parameters.setPictureFormat(PixelFormat.JPEG);
    mCamera.setDisplayOrientation(90);
    requestLayout();
    try {
        mCamera.setParameters(parameters);
    } catch (Exception e) {
        System.out.print("hih");
    }
    mCamera.startPreview();
    mCameraActive = true;
}

/**
 * @param sizes
 *            of type List
 * @param w
 *            of type int
 * @param h
 *            of type int
 * @return optionalSize of type Size function which will find the exact size
 *         required for teh camera view
 * @since 16 Oct 2012
 */
private Size getPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    if (sizes == null)
        return null;
    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;
    int targetHeight = h;
    for (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);
        }
    }

    // Cannot find the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }

    return optimalSize;
}

/**
 * @author rajeshcp
 * @since 16 Oct 2012
 */
public static interface IQCameraCallback {
    public void onCameraCallback(final int type, final Object param);
}
}

试试这个代码已经用于一个项目,希望这会有所帮助

于 2013-02-19T14:03:12.057 回答