Android全屏摄像头 – 同时保持摄像头选择的比例

我们正在尝试构建类似于Instagram Camera屏幕的东西。 即允许用户拍摄square照片。 在执行此操作时,Ui必须能够让用户在fullScreen模式下看到相机。 我们想强制用户以portrait模式拍摄图像

获得相机可能的比率

我们正在计算camerabest比例

  private Camera.Size getOptimalPreviewSize(List sizes, int w, int h) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) h / w; if (sizes == null) { return null; } Camera.Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; for (Camera.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); } } if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Camera.Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; } 

全屏显示。

 public FrameLayout setCameraLayout(int width, int height) { float newProportion = (float) width / (float) height; // Get the width of the screen int screenWidth = this.customCameraActivity.getWindowManager().getDefaultDisplay() .getWidth(); int screenHeight = this.customCameraActivity.getWindowManager().getDefaultDisplay() .getHeight(); float screenProportion = (float) screenWidth / (float) screenHeight; // Get the SurfaceView layout parameters ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)preview.getLayoutParams(); if (newProportion > screenProportion) { lp.width = screenWidth; lp.height = (int) ((float) screenWidth / newProportion); } else { lp.width = (int) (newProportion * (float) screenHeight); lp.height = screenHeight; } //calculate the amount that takes to make it full screen (in the `height` parameter) float propHeight = screenHeight / lp.height; //make it full screen( lp.width = (int)(lp.width * propHeight); lp.height = (int)(lp.height * propHeight); frameLayout.setLayoutParams(lp); return frameLayout; } 

setCameraLayout来电者

OnCreate来自Activity ,之后是surfaceChanged

  @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (getHolder().getSurface() == null) { return; } try { cameraManager.getCamera().stopPreview(); } catch (Exception e) { // tried to stop a non-existent preview } try { Camera.Parameters cameraSettings = cameraManager.getCamera().getParameters(); cameraSettings.setPreviewSize(mPreviewSize.width, mPreviewSize.height); this.cameraView.setCameraLayout(mPreviewSize.width, mPreviewSize.height); cameraManager.getCamera().setParameters(cameraSettings); cameraManager.getCamera().setPreviewDisplay(holder); cameraManager.getCamera().startPreview(); } catch (Exception e) { Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } 

目标

全屏摄像头预览在手机上。

问题

现在我们正在预览,没有失真,这是好的! 它与phone height相同,也很好但! preview的宽度大于phone width (当然),因此事实certificate相机的中心不在手机的中心。 我们考虑过的可能解决方案:

  1. move布局向左move到负位置,使预览中心位于屏幕中央。
  2. crop布局并仅绘制应对phone screens可见的new preview的中心

任何想法如何克服这个问题?

非常感谢! 🙂

我通过设置SurfaceView的重力成功地使预览居中:

 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(wid, hei); lp.gravity = Gravity.CENTER; mSv.setLayoutParams(lp); 

代码片段是从这里获取的 ,如果您有耐心解密它,欢迎您使用该代码。 我想我正在解决类似的问题(预览旋转,扭曲,装入/填充)

祝你好运。

如果我从代码片段中了解到,则每次用户更改方向或旋转相机时都会重新实例化相机。 有什么理由这样做吗?

为什么不将预览限制为仅限纵向并且具有旋转的重叠视图? 我很确定这是其他人(Instagram,Snapchat等)所做的。 如果我能find它,我将编辑一个这样的例子。