使用FrameLayout时,Camera Preview会拉伸

时间:2014-01-21 10:15:30

标签: android android-camera android-framelayout

我发现当我使用PreviewFrameLayout时,CameraPreview显示在一个小区域中,当我使用宽高比和FrameLayout时,它会被拉伸。 以下是我目前用于设置Camera Preview和FrameLayout大小的代码:

   private Size getOptimalPreviewSize(Activity currentActivity,
        List<Size> sizes, double targetRatio) {
    // Use a very small tolerance because we want an exact match.
    final double ASPECT_TOLERANCE = 0.001;
    if (sizes == null) return null;

    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    // Because of bugs of overlay and layout, we sometimes will try to
    // layout the viewfinder in the portrait orientation and thus get the
    // wrong size of mSurfaceView. When we change the preview size, the
    // new overlay will be created before the old one closed, which causes
    // an exception. For now, just get the screen size

    Display display = currentActivity.getWindowManager().getDefaultDisplay();

    int targetHeight = Math.min(display.getHeight(), display.getWidth());

    if (targetHeight <= 0) {
        // We don't know the size of SurfaceView, use screen height
        targetHeight = display.getHeight();

    }

    // Try to find an size match aspect ratio and size
    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. This should not happen.
    // Ignore the requirement.
    if (optimalSize == null) {
        Log.w(TAG, "No preview size match the aspect ratio");
        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;
}

//this is what I really want to use:
private Size getDesiredPictureSize(List<Size> supportedSizeList)
{
    //Resolution is widthxheight

    Size result=null;
    final int minArea=500*500;  
    final int maxArea=1000*1000;
    for(Size size:supportedSizeList)
    {
        if(size.width*size.height>minArea && size.width*size.height<maxArea)
        {
            if(result==null)
                result=size;
            else
            {
                int resultArea=result.width*result.height;
                int sizeArea=size.width*size.height;
                if(resultArea<sizeArea)
                {   
                    result=size;
                }   
            }
        }
    }
    return result;
}

//I am just testing with this method:  
private Size getBestPictureSize(List<Size> supportedSizeList)
{
    Size result=null;
    for(Size size:supportedSizeList)
    {
        if(result==null)
            result=size;
            int resultArea=result.width*result.height;
            int sizeArea=size.width*size.height;
            if(resultArea<sizeArea)
                result=size;
    }
    return result;
}

List<Size> supportedPictureSizes=mParameters.getSupportedPictureSizes();
    List<Size> supportedPreviewSizes=mParameters.getSupportedPreviewSizes();

        Log.d(TAG,"Setting picture size");
        mPictureSize=getBestPictureSize(supportedPictureSizes);
        Log.d(TAG,"The Picture Width: "+mPictureSize.width+" The Picture Height: "+mPictureSize.height);

    double targetRatio=(double)mPictureSize.width/mPictureSize.height;
    mPreviewSize=getOptimalPreviewSize(this,supportedPreviewSizes, targetRatio);
    Log.d(TAG, "The Preview Width:"+mPreviewSize.width+" Preview Height: "+mPreviewSize.height);
    double ratio=(double)mPreviewSize.width/mPreviewSize.height;
    Log.d(TAG,"Picture Ratio: "+targetRatio);
    Log.d(TAG, "Preview Ratio: "+ratio);
    int new_width=0, new_height=0;
    if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT)
    {
        if((double)previewFrame.getWidth()/previewFrame.getHeight()<ratio)
        {
            new_width=(int)(Math.round(previewFrame.getHeight()*ratio));
            new_height=getWindowManager().getDefaultDisplay().getHeight();
        }
        else
        {
            new_width=getWindowManager().getDefaultDisplay().getHeight();
            new_height=(int)Math.round((double)new_width/ratio);
        }
      }

 if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE)
    {
        if((double)previewFrame.getWidth()/previewFrame.getHeight()<ratio)
        {
            new_width=(int)(Math.round(previewFrame.getHeight()*ratio));
            new_height=getWindowManager().getDefaultDisplay().getHeight();
        }
        else
        {
            new_width=getWindowManager().getDefaultDisplay().getWidth();
            new_height=(int)Math.round((double)new_width/ratio);
        }
    }


//Should I set the size of the container first???
 mParameters.setPictureSize(mPictureSize.width, mPictureSize.height);
    mParameters.setPreviewSize(mPreviewSize.width,mPreviewSize.height);
    previewFrame.setLayoutParams(new RelativeLayout.LayoutParams(new_width, new_height));  

我发现使用AOSP中的PreviewFrameLayout在一个方框中显示我的CDamera预览而不是全屏,我可以在Camera Preview does not appear full screen(displayed in a box)找到我使用PreviewFrameLayout的详细信息

1 个答案:

答案 0 :(得分:1)

首先,如果你在xml中使用FrameLayout来托管 previewFrame ,你也应该调用

previewFrame.setLayoutParams(new FrameLayout.LayoutParams(new_width, new_height));

接下来,您可以看到getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAITConfiguration.ORIENTATION_LANDSCAPE是否进行相同的计算,因此这种方向根本不相关。

最后,您应该在屏幕旋转时set the camera orientation

我相信你可以找到一个[这里的工作示例](https://stackoverflow.com/a/19448369/192373)。