如何设置相机预览大小平方纵横比在平方SurfaceView(如Instagram)

我试图开发自己的相机活动,但我有一个问题,我无法解决…

我想要的,是一个非常类似于Instagram的相框,这是我得到:

我的形象

当我应该得到这样的东西:

Instagram的图像

和…

我的第二个形象

当我应该得到像这样的东西:

Instagram 2

我想我只是使用SurfaceView和Camera预览

Camera.Parameters parameters = camera.getParameters(); camera.setDisplayOrientation(90); 

和自定义SurfaceView:

 public class SquaredSurfaceView extends SurfaceView { private int width; private int height; public SquaredSurfaceView(Context context) { super(context); } public SquaredSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); } public SquaredSurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec); height = width; setMeasuredDimension(width, width); } public int getViewWidth() { return width; } public int getViewHeight() { return height; } 

}

我在做什么错? 🙁

如前所述,您需要find正确的预览大小(宽高比为1:1),并且可能必须使用FrameLayout作为SurfacePreview。 看起来你有和宽高比问题也许你有正确的预览大小,但你把它放在一个不正确的布局。

另一个解决scheme可能(就像Instagram一样)使全尺寸的相机,然后隐藏一些地方的布局,只是为了让它看起来像一个正方形。 然后通过软件,你将不得不削减图像,使其成为一个真正的广场。

希望这可以帮助你

我的解决scheme是第二答案,但因为我们需要旋转相机90º是必要的切换宽度HEIGTH,像这样…

  camera.setDisplayOrientation(90); Camera.Parameters params= camera.getParameters(); surfaceView.getLayoutParams().width=params.getPreviewSize().height; surfaceView.getLayoutParams().height=params.getPreviewSize().width; 

希望这个解决scheme帮助 :d

我的解决scheme更像是build立一个正方形的面具,然后把它放在预览面上。

您将主要需要3件东西,首先是方形框架组件。 我做了一个自定义组件:

 package com.example.squaredviewer; import android.content.Context; import android.util.AttributeSet; import android.view.Display; import android.view.WindowManager; import android.widget.RelativeLayout; /** * Created by yadirhb on 14-08-2015. */ public class SquaredFrame extends RelativeLayout{ public SquaredFrame(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int size = Math.min(getMeasuredWidth(), getMeasuredHeight()); setMeasuredDimension(size, size); } } 

根据您正在开发的Android API版本,您可能需要添加另一个构造函数重载。 对于Kitkat来说,这很好。

第二步是构build布局:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:visibility="visible"> <RelativeLayout android:id="@+id/camera_preview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="false" android:layout_alignParentTop="false" android:layout_centerInParent="true" android:background="#ffffff"> </RelativeLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="#131008"> </LinearLayout> <com.example.squaredviewer.SquaredFrame android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"></com.example.squaredviewer.SquaredFrame> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="#131008" /> </LinearLayout> </RelativeLayout> 

请注意,RelativeLayout“camera_preview”是用来渲染预览的,它是居中的,并有一个包含平方分量的LinearLayout。 这实际上是“蒙版”,它涵盖了相机预览。 另外请注意,除了透明的SquaredFrame外,其他两个都用黑色背景着色。

现在是表面视图,用于根据高宽比确定表面大小的相机预览。

 public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private final String TAG = "PIC-FRAME"; private SurfaceHolder mHolder; private Camera mCamera; private Display display; public CameraPreview(Activity context, Camera camera) { super(context); mCamera = camera; display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); // 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); setKeepScreenOn(true); } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. this.getHolder().removeCallback(this); } public void surfaceChanged(SurfaceHolder holder, int format, int w, int 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; } try { // stop preview before making changes mCamera.stopPreview(); // set preview size and make any resize, rotate or // reformatting changes here // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = mCamera.getParameters(); // You need to choose the most appropriate previewSize for your app Camera.Size previewSize = parametes.getSupportedPreviewSizes().get(0); parameters.setPreviewSize(previewSize.width, previewSize.height); // start preview with new settings mCamera.setParameters(parameters); // Set the holder size based on the aspect ratio int size = Math.min(display.getWidth(), display.getHeight()); double ratio = (double) previewSize.width / previewSize.height; mHolder.setFixedSize((int)(size * ratio), size); mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e) { Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } } } 

现在,所有的事情都必须在活动课上

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_picture_taker); mDecorView = getWindow().getDecorView(); //mCamera = a camera instance; // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); //Layout where camera preview is shown. RelativeLayout preview = (RelativeLayout) findViewById(R.id.camera_preview); //FrameLayout stack controllers inside and superpose them. preview.addView(mPreview, 0); // TODO } 

有点长,但我希望这对多个人有帮助。 🙂

我有一个方形的视图相同的问题 – 解决它只需将SurfaceView的相机大小设置为我想绘制它的视图的大小。 没有复杂的计算,它适用于我。 看到我的答复在这里的整个方法: https : //stackoverflow.com/a/39430615/5181489

 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { ... params.setPreviewSize(viewParams.height, viewParams.width); camera.setParameters(params); 

你可以用这个来得到pictureSize:

 public static void initialCameraPictureSize(Context context, android.hardware.Camera.Parameters parameters) { List list = parameters.getSupportedPictureSizes(); if(list != null) { android.hardware.Camera.Size size = null; Iterator iterator = list.iterator(); do { if(!iterator.hasNext()) break; android.hardware.Camera.Size size1 = (android.hardware.Camera.Size)iterator.next(); if(Math.abs(3F * ((float)size1.width / 4F) - (float)size1.height) < 0.1F * (float)size1.width && (size == null || size1.height > size.height && size1.width < 3000)) size = size1; } while(true); if(size != null) parameters.setPictureSize(size.width, size.height); else Log.e("CameraSettings", "No supported picture size found"); } } 

它是如此艰苦。 不容易。

第一件事:你定义2黑色的Linear Layout以获得您张贴的用户界面。

第二件事:你需要从完整的图片切换到方形图片。

如何切割,你需要使用scaleBitmap方法。

或者你想要真正的自定义相机? 可以在这里检查