2013-06-21 4 views
3

Я хочу получить полноэкранный портретный просмотр камеры. Используя образец Google, предварительный просмотр находится в альбомном формате на экране портрета. Когда я установил предварительный просмотр до 480 x 864, обратный размер рабочего ландшафта, я получаю ошибку setParameters.Предварительный просмотр камеры портретный наборParameters не удалось

Я прочитал весь StackOverflow, который я могу найти, но я не могу понять, почему размеры, поддерживаемые в ландшафте, не отображаются в портрете. Я также не могу найти способ принудительного просмотра в полноэкранном режиме. Приложение «Камера» на телефоне обеспечивает просмотр в полноэкранном режиме, поэтому я знаю, что это не аппаратное ограничение.

Я тестирую с Droid 3 работает Android 2.3.3

Я был бы признателен за любые предложения.

public class SimplePreview extends ViewGroup implements SurfaceHolder.Callback { 
private final String TAG = "Preview"; 

SurfaceView mSurfaceView; 
SurfaceHolder mHolder; 
Size mPreviewSize; 
List<Size> mSupportedPreviewSizes; 
Camera mCamera; 
int cameraId; 
Activity activity; 

public SimplePreview(Activity context, int defaultCamera) { 
    super(context); 
    activity = context; 
    cameraId = defaultCamera; 
    mSurfaceView = new SurfaceView(context); 
    addView(mSurfaceView); 

    // Install a SurfaceHolder.Callback so we get notified when the 
    // underlying surface is created and destroyed. 
    mHolder = mSurfaceView.getHolder(); 
    mHolder.addCallback(this); 
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
} 

public void setCamera(Camera camera) { 
    mCamera = camera; 
    if (mCamera != null) { 
     mSupportedPreviewSizes = mCamera.getParameters() 
       .getSupportedPreviewSizes(); 
     requestLayout(); 
    } 
} 

public void switchCamera(Camera camera) { 
    setCamera(camera); 
    try { 
     camera.setPreviewDisplay(mHolder); 
    } catch (IOException exception) { 
     Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 
    } 
    Camera.Parameters parameters = camera.getParameters(); 
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
    requestLayout(); 

    camera.setParameters(parameters); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    // We purposely disregard child measurements because act as a 
    // wrapper to a SurfaceView that centers the camera preview instead 
    // of stretching it. 
    final int width = resolveSize(getSuggestedMinimumWidth(), 
      widthMeasureSpec); 
    final int height = resolveSize(getSuggestedMinimumHeight(), 
      heightMeasureSpec); 

    Log.i(TAG, "setting View measured dimensions to width: " + width 
      + " height: " + height); 

    setMeasuredDimension(width, height); 

    if (mSupportedPreviewSizes != null) { 
     mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, 
       height); 
    } 
} 

@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); 
     } 
    } 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    // Surface will be destroyed when we return, so stop the preview. 
    if (mCamera != null) { 
     mCamera.stopPreview(); 
    } 
} 

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { 
    final double ASPECT_TOLERANCE = 0.1; 
    double targetRatio = (double) w/h; 
    if (sizes == null) 
     return null; 

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

    int targetHeight = h; 

    // Try to find an size match aspect ratio and size 
    for (Size size : sizes) { 
     Log.v(TAG, " width: " + size.width + " height: " + 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); 
     } 
    } 

    // Cannot find the one match the aspect ratio, ignore the requirement 
    if (optimalSize == null) { 
     minDiff = Double.MAX_VALUE; 
     for (Size size : sizes) { 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 
    } 

    Log.i(TAG, "optimal preview width: " + optimalSize.width + " height: " 
      + optimalSize.height); 

    return optimalSize; 
} 

public void surfaceCreated(SurfaceHolder holder) { 
    // The Surface has been created, acquire the camera and tell it where 
    // to draw. 
    try { 
     if (mCamera != null) { 

      final int width = getWidth(); 
      final int height = getHeight(); 

      Log.i(TAG, "view width: " + width + " height: " + height); 

      if (height > width) { 
       Log.i(TAG, "in portrait mode so rotate camera preview"); 
       // THis line fixed the camera display orientation. seems to 
       // have to be called before setPreviewDisplay() 

       mCamera.setDisplayOrientation(90); 

      } 

      mCamera.setPreviewDisplay(holder); 

     } 
    } catch (IOException exception) { 
     Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 
    } 
} 

/** 
* orientation and rotation work done here. Now that the size is known, set 
* up the camera parameters and begin the preview. 
*/ 
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 

    if (mCamera != null) { 

     mCamera.stopPreview(); 

     Camera.Parameters parameters = mCamera.getParameters(); 

     // mCamera.setDisplayOrientation(90); 
     final int width = getWidth(); 
     final int height = getHeight(); 

     Log.i(TAG, "view width: " + width + " height: " + height); 

     if (height > width) { 

      Log.i(TAG, "portrait: setting preview width: " + 480 
        + " height: " + 864); 

      parameters.setPreviewSize(480, 864); 

      // had no effect 
      parameters.set("orientation", "portrait"); 

     } else { 
      Log.i(TAG, "landscape: setting preview width: " 
        + mPreviewSize.width + " height: " 
        + mPreviewSize.height); 

      parameters.setPreviewSize(mPreviewSize.width, 
        mPreviewSize.height); 
     } 
     requestLayout(); 

        // *** following line throws setParameters failed error *** 
     mCamera.setParameters(parameters); 

     mCamera.startPreview(); 
    } 
} 
} 

И призыв от OnCreate своей деятельности (в):

preview = new SimplePreview(this, defaultCameraId); 
    setContentView(preview); 

ответ

4

попробовать этот код:

package com.example.dragme; 

import java.io.IOException; 
import java.util.List; 
import android.app.Activity; 
import android.content.Context; 
import android.content.res.Configuration; 
import android.hardware.Camera; 
import android.os.Build; 
import android.util.Log; 
import android.view.Display; 
import android.view.Surface; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private SurfaceHolder mHolder; 
    public Camera mCamera; 

    private static boolean DEBUGGING = true; 
    private static final String LOG_TAG = "CameraPreviewSample"; 
    private static final String CAMERA_PARAM_ORIENTATION = "orientation"; 
    private static final String CAMERA_PARAM_LANDSCAPE = "landscape"; 
    private static final String CAMERA_PARAM_PORTRAIT = "portrait"; 
    protected Activity mActivity; 

    protected List<Camera.Size> mPreviewSizeList; 
    protected List<Camera.Size> mPictureSizeList; 
    protected Camera.Size mPreviewSize; 
    protected Camera.Size mPictureSize; 


    public CameraPreview(Context context, Camera camera) { 
     super(context); 

     mActivity=(Activity)context; 
     mCamera = camera; 

     // 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) { 
     // The Surface has been created, now tell the camera where to draw the preview. 
     try { 
      mCamera.setPreviewDisplay(holder); 
      mCamera.startPreview(); 
     } catch (IOException e) { 
      Log.d("CameraView", "Error setting camera preview: " + e.getMessage()); 
     } 
    } 

    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) { 
     // 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 cameraParams = mCamera.getParameters(); 
      boolean portrait = isPortrait(); 
      configureCameraParameters(cameraParams, portrait); 

      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 

     } catch (Exception e){ 
      Log.d("CameraView", "Error starting camera preview: " + e.getMessage()); 
     } 
    } 

    public void onPause() { 
     if (null == mCamera) { 
      return; 
     } 
     mCamera.stopPreview(); 
     mCamera.release(); 
     mCamera = null; 
    } 


    protected void configureCameraParameters(Camera.Parameters cameraParams, boolean portrait) { 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { // for 2.1 and before 
      if (portrait) { 
       cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_PORTRAIT); 
      } else { 
       cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_LANDSCAPE); 
      } 
     } else { // for 2.2 and later 
      int angle; 
      Display display = mActivity.getWindowManager().getDefaultDisplay(); 
      switch (display.getRotation()) { 
       case Surface.ROTATION_0: // This is display orientation 
        angle = 90; // This is camera orientation 
        break; 
       case Surface.ROTATION_90: 
        angle = 0; 
        break; 
       case Surface.ROTATION_180: 
        angle = 270; 
        break; 
       case Surface.ROTATION_270: 
        angle = 180; 
        break; 
       default: 
        angle = 90; 
        break; 
      } 
      Log.v(LOG_TAG, "angle: " + angle); 
      mCamera.setDisplayOrientation(angle); 
     } 

     cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
     cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height); 
     if (DEBUGGING) { 
      Log.v(LOG_TAG, "Preview Actual Size - w: " + mPreviewSize.width + ", h: " + mPreviewSize.height); 
      Log.v(LOG_TAG, "Picture Actual Size - w: " + mPictureSize.width + ", h: " + mPictureSize.height); 
     } 

     mCamera.setParameters(cameraParams); 
    } 


    public boolean isPortrait() { 
     return (mActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT); 
    } 
} 
+0

Спасибо. Этот предварительный просмотр создал полноэкранный портрет. Однако, эта линия –

+0

вы хотите посмотреть портрет? –

+0

mCamera.setDisplayOrientation (angle); выбросил ошибку, в результате чего дисплей повернулся на 90 градусов против часовой стрелки. Я исправил это, добавив следующий код в surfaceCreated() \t final int width = getWidth(); \t final int height = getHeight(); \t, если (высота> ширина) {\t \t \t \t \t \t \t \t \t mCamera.setDisplayOrientation (90); \t \t \t \t} \t \t \t \t \t mCamera.setPreviewDisplay (держатель); \t mCamera.startPreview(); –