我正在尝试创建与Instagram应用程序相同的相机预览,但我的相机预览显示与Instagram相同的帧,但是当我拍摄照片时它会给我全屏图像。
以下是我的代码:
XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.spurtree.townsee.utils.camera.MyFrameLayout
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</FrameLayout>
Myframelayout:
class MyFrameLayout extends FrameLayout {
private static final float RATIO = 4f / 3f;
public MyFrameLayout(Context context) {
super(context);
}
public MyFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public MyFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom();
int maxWidth = (int) (heigthWithoutPadding * RATIO);
int maxHeight = (int) (widthWithoutPadding / RATIO);
if (widthWithoutPadding > maxWidth) {
width = maxWidth + getPaddingLeft() + getPaddingRight();
} else {
height = maxHeight + getPaddingTop() + getPaddingBottom();
}
setMeasuredDimension(width, height);
}
相机预览类:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private Context mContext;
private SurfaceHolder mHolder;
private Camera mCamera;
public List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
public CameraPreview(Context context, Camera camera) {
super(context);
mContext = context;
mCamera = camera;
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
for (Camera.Size str : mSupportedPreviewSizes)
Log.e(TAG, str.width + "/" + str.height);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// empty. surfaceChanged will take care of stuff
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged => w=" + w + ", h=" + h);
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or reformatting changes here
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.getParameters().setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes);
}
float ratio;
if (mPreviewSize.height >= mPreviewSize.width)
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
else
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
// One of these methods should be used, second method squishes preview slightly
setMeasuredDimension(width, (int) (width * ratio));
// setMeasuredDimension((int) (width * ratio), height);
}
public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes)
{
final double ASPECT_TOLERANCE = 0.05;
if( sizes == null )
return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
Point display_size = new Point();
Activity activity = (Activity)this.getContext();
{
Display display = activity.getWindowManager().getDefaultDisplay();
display.getSize(display_size);
// Log.d(TAG, "display_size: " + display_size.x + " x " + display_size.y);
}
double targetRatio = calculateTargetRatioForPreview(display_size);
int targetHeight = Math.min(display_size.y, display_size.x);
if( targetHeight <= 0 ) {
targetHeight = display_size.y;
}
// Try to find the size which matches the aspect ratio, and is closest match to display height
for(Camera.Size size : sizes)
{
Log.d(TAG, " supported preview size: " + size.width + ", " + size.height);
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 )
// {
// // can't find match for aspect ratio, so find closest one
// Log.d(TAG, "no preview size matches the aspect ratio");
// optimalSize = getClosestSize(sizes, targetRatio);
// }
//
// Log.d(TAG, "chose optimalSize: " + optimalSize.width + " x " + optimalSize.height);
// Log.d(TAG, "optimalSize ratio: " + ((double) optimalSize.width / optimalSize.height));
return optimalSize;
}
private double calculateTargetRatioForPreview(Point display_size)
{
double targetRatio = 0.0f;
targetRatio = ((double)mCamera.getParameters().getPictureSize().width) / (double)mCamera.getParameters().getPictureSize().height;
//targetRatio = ((double)display_size.x) / (double)display_size.y;
return targetRatio;
}
public void refreshCamera(Camera camera) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
mCamera = camera;
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
我查了许多对我没有帮助的帖子。