将相机预览适合大于显示器的SurfaceView

我有一个Android应用程序需要全屏显示相机预览,无论getSupportedPreviewSizes()给出的预览大小没有失真。 我希望这会在高度或宽度上裁剪一些预览,但这并不关心我。 我之所以这样做是因为某些安卓摄像头(例如三星Galaxy SII前置摄像头)不会返回任何与显示器具有相同宽高比的预览,因此需要进行拉伸和剪裁。

是否可以将相机预览完全增加到大于显示尺寸的视图? 通过简单地将曲面视图的布局参数设置为match_parent,可以使SurfaceView大于返回的预览像素尺寸,但这会导致某些方向的失真,并且只有在预览填充显示之前才可能。 这似乎表明在显示器外部进行预览是不可能的,并且硬件(或OS)限制了这种行为。

关于这个主题还有另一个问题 ,但是这个问题声称不可能创建大于屏幕尺寸的SurfaceView,这是错误的,正如我在日志记录中发现的那样。 然而,似乎情况是摄像机预览无法增长到巨大的SurfaceView的全尺寸。

我的尝试:

我有一个相对布局,在它内部是一个FrameLayout,在其中我创建了一个SurfaceView。 整个相对布局的宽度设置在635dp以下,这是设备屏幕尺寸的两倍。 FrameLayout匹配此大小调整,SurfaceView也是如此(稍后以编程方式添加)

     

以下是获取和设置预览大小的代码。 在这里,我想让相机预览展开以填充整个FrameLayout(屏幕宽度的两倍)。 视图完全正常显示和破坏,因此我删除与此特定问题无关的代码,因为它分散了基本问题,并且我尝试轻松简单地将视图扩展为大于显示大小的视图。

 public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { ... public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { Camera.Parameters parameters = mCamera.getParameters(); final DisplayMetrics dm = this.getResources().getDisplayMetrics(); //getBestPreviewSize returns the best preview size, don't worry //but some devices do not return one for all camera matching the aspect ratio cameraSize = getBestPreviewSize(parameters, dm.heightPixels, dm.widthPixels); if (cameraSize!=null) { parameters.setPreviewSize(cameraSize.width, cameraSize.height); mCamera.setParameters(parameters); } FrameLayout.LayoutParams frameParams = (FrameLayout.LayoutParams) this.getLayoutParams(); frameParams.width = 800; //For argument's sake making this ~double the width of the display. Same result occurs if I use MATCH_PARENT frameParams.height = LayoutParams.MATCH_PARENT; this.setLayoutParams(frameParams); try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); Log.d("surfChange","W/H of CamPreview (child) is "+this.getWidth()+"/"+this.getHeight()+" while parent is "); Log.d("surfChange","W/H of holder (child) is "+mHolder.getSurfaceFrame().width()+"/"+mHolder.getSurfaceFrame().height()+" while parent is "); } catch (Exception e){ } } }; 

我担心在这种努力中取得成功的唯一方法是以某种方式渲染到openGL表面,但这显然可能在全彩色中太慢。 如果可以简单地拉伸和剪裁相机预览,那也是一种痛苦。

提前感谢任何解决方案的尝试。

好的,我知道这是一个很晚的答案但是有可能。 以下是Android SDK示例中的代码。 要查看其余的代码来实现这个下载android sdk示例并转到Samples/android-10(one I used, could try whichever you want to target)/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java

 class PreviewSurface extends ViewGroup implements SurfaceHolder.Callback { ... @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; if (mPreviewSize != null) { previewWidth = mPreviewSize.width; previewHeight = mPreviewSize.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); } } } } 

此代码旨在使预览适合最小尺寸(不会弄乱aspcect比率),并且中心在另一个维度上具有黑条。 但是如果你将>翻转为< 而不是你将实现你想要的。 例如:

 if (width * previewHeight < height * previewWidth) {...