he creado una aplicación de cámara basado en el tutorial. la vista previa de la clase que yo uso es de la api Demos «CameraPreview». He añadido una modificación de aquí (vista previa siempre fue girada 90°). Así es como me puse de vista previa tamaño:

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    //Now that the size is known, set up the camera parameters and begin
    //the preview.
    Camera.Parameters parameters = mCamera.getParameters();
    Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

    if (display.getRotation() == Surface.ROTATION_0) {
        parameters.setPreviewSize(mPreviewSize.height, mPreviewSize.width);
        mCamera.setDisplayOrientation(90);
    }

    if (display.getRotation() == Surface.ROTATION_90) {
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    }

    if (display.getRotation() == Surface.ROTATION_180) {
        parameters.setPreviewSize(mPreviewSize.height, mPreviewSize.width);
    }

    if (display.getRotation() == Surface.ROTATION_270) {
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        mCamera.setDisplayOrientation(180);
    }
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

    requestLayout();

    mCamera.setParameters(parameters);
    mCamera.startPreview();
}

Pero la vista previa se muestra con mal de la relación de aspecto. Es debido a que el código de arriba o probablemente a causa de la disposición debo usar?:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<Button
    android:id="@+id/button_capture"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true" 
    android:text="@string/capture" />

<FrameLayout
    android:id="@+id/camera_preview"
    android:layout_width="100dp"
    android:layout_height="match_parent"/>

Entonces, ¿cómo conseguir la relación de aspecto correcta? Gracias de antemano.

P. S. he leído la respuesta de: Android previa de la cámara un aspecto extraño
Pero esto no está funcionando para mí.

tal vez usted podría cerrar este tema ?
por qué? lo que ha cambiado?
en primer lugar usted no tiene que creer, 2º no tengo tiempo de probar las otras soluciones (publicado un año después de la publicación de la pregunta). Tan pronto como he tratado de las otras respuestas me dará retroalimentación. Hasta entonces todo está bien…

OriginalEl autor dermoritz | 2013-07-23

5 Comentarios

  1. 22

    Intente cambiar la vista previa de tamaño, con la adición de esta función:

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

    Y el ajuste de los tamaños de estos valores optimizados:

    List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
    Camera.Size optimalSize = getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
    
    parameters.setPreviewSize(optimalSize.width, optimalSize.height);

    Espero que esto funcione 🙂

    Saludos

    Henric

    como dije en mi pregunta estoy usando este código (es a partir de la Api Demos «CameraPreview»). Creo que el problema se basa a mi diseño, y cómo puedo agregar la vista previa?
    Esta respuesta es bastante útil,debe ser aceptada.
    No es un problema de diseño! necesita configurar los parámetros de uno de los mCamera-objeto de una línea por encima mCamera.startPreview() en el CameraPreivew.javade clase. A mí me funciona. Esta respuesta debe ser aceptada!
    funciona muy bien gracias

    OriginalEl autor Henric

  2. 5

    El siguiente código modifica la anchura/altura de la vista previa de la cámara de contenedor para que coincida con la relación de aspecto de la vista previa de la cámara.

        Camera.Size size = camera.getParameters().getPreviewSize();
    
        //landscape
        float ratio = (float)size.width/size.height;
    
        //portrait
        //float ratio = (float)size.height/size.width;
    
        preview = (FrameLayout) findViewById(R.id.camera_preview);
    
        int new_width=0, new_height=0;
        if(preview.getWidth()/preview.getHeight()<ratio){
            new_width = Math.round(preview.getHeight()*ratio);
            new_height = cameraPreview.getHeight();
        }else{
            new_width = preview.getWidth();
            new_height = Math.round(preview.getWidth()/ratio);
        }
        preview.setLayoutParams(new FrameLayout.LayoutParams(new_width, new_height));
    Buena idea, pero varios errores deben ser limpiados…. 1. Usted debe dividir flotar por flotan en su «si» – ahora que está dividiendo números enteros. 2. cameraPreview debe ser vista previa. 3. usted debe asegurarse de que las opiniones están dispuestas a realizar este.

    OriginalEl autor gtsouk

  3. 2

    El uso de la solución anterior, utilizando el método privado de Tamaño getOptimalPreviewSize(Lista de tamaños, int w, int h).
    Trabajó muy bien! Yo estaba teniendo problemas con la relación de aspecto de la orientación vertical: Aquí mi solución utilizando. Mezcla con android documentación:

      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
                Camera.Parameters params = mCamera.getParameters();
                params.set("orientation", "portrait");
                Size optimalSize=getOptimalPreviewSize(params.getSupportedPreviewSizes(),  getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
                params.setPreviewSize(optimalSize.width, optimalSize.height);
                mCamera.setParameters(params);
                //start preview with new settings
                try {
    
                    mCamera.setPreviewDisplay(mHolder);
                    mCamera.startPreview();
    
                } catch (Exception e){
                    Log.d(TAG, "Error starting camera preview: " + e.getMessage());
                }
            }
        }

    OriginalEl autor supersabbath

  4. 2

    problema está realmente en forma de disposición de las cosas.
    hay anular onLayout en Preview clase. idea de su trabajo es el conjunto de niño SurfaceView tamaño de acuerdo a encontrar el óptimo Size. pero no tomar la rotación en cuenta, por lo que necesita para hacerlo por ti mismo:

      if (mPreviewSize != null) {
        previewWidth = mPreviewSize.height;
        previewHeight = mPreviewSize.width;
      }

    lugar de

      if (mPreviewSize != null) {
        previewWidth = mPreviewSize.width;
        previewHeight = mPreviewSize.height;
      }

    Truco es cambiar la anchura y la altura que se realiza debido a la rotación de 90 grados alcanzados por

      mCamera.setDisplayOrientation(90);

    Usted también podría considerar la posibilidad de que se bifurcan hijo tamaño de la vista previa, dependiendo de la orientación que se establece en

      public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
          //...
      }

    (proporcionado por mí código es siempre para la rotación de 90 grados, 180 usted no tiene que hacer anyhing y cuando no establece ninguna rotación, no hay necesidad de cambiar la anchura y altura)

    Otra cosa que vale la pena mencionar – a la hora de calcular getOptimalPreviewSize para el caso cuando usted tiene la rotación y el intercambio de niño ancho y la altura que también debe pasar de los padres(Preview) la anchura y la altura se intercambian en onMeasure:

    if (mSupportedPreviewSizes != null) {
      //noinspection SuspiciousNameCombination
      final int previewWidth = height;
      //noinspection SuspiciousNameCombination
      final int previewHeight = width;
      mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, previewWidth, previewHeight);
    }

    OriginalEl autor w1ld.b0ar

  5. 1

    Henric la respuesta no trabajo para mí, así que me he creado otro método que determina el óptimo tamaño de la vista previa para cualquier cámara, dado el objetivo de la vista actual de la anchura y la altura, y también la actividad de orientación:

    public static Size getOptimalPreviewSize(List<Camera.Size> cameraPreviewSizes, int targetWidth, int targetHeight, boolean isActivityPortrait) {
    if (CommonUtils.isEmpty(cameraPreviewSizes)) {
    return null;
    }
    int optimalHeight = Integer.MIN_VALUE;
    int optimalWidth = Integer.MIN_VALUE;
    for (Camera.Size cameraPreviewSize : cameraPreviewSizes) {
    boolean isCameraPreviewHeightBigger = cameraPreviewSize.height > cameraPreviewSize.width;
    int actualCameraWidth = cameraPreviewSize.width;
    int actualCameraHeight = cameraPreviewSize.height;
    if (isActivityPortrait) {
    if (!isCameraPreviewHeightBigger) {
    int temp = cameraPreviewSize.width;
    actualCameraWidth = cameraPreviewSize.height;
    actualCameraHeight = temp;
    }
    } else {
    if (isCameraPreviewHeightBigger) {
    int temp = cameraPreviewSize.width;
    actualCameraWidth = cameraPreviewSize.height;
    actualCameraHeight = temp;
    }
    }
    if (actualCameraWidth > targetWidth || actualCameraHeight > targetHeight) {
    //finds only smaller preview sizes than target size
    continue;
    }
    if (actualCameraWidth > optimalWidth && actualCameraHeight > optimalHeight) {
    //finds only better sizes
    optimalWidth = actualCameraWidth;
    optimalHeight = actualCameraHeight;
    }
    }
    Size optimalSize = null;
    if (optimalHeight != Integer.MIN_VALUE && optimalWidth != Integer.MIN_VALUE) {
    optimalSize = new Size(optimalWidth, optimalHeight);
    }
    return optimalSize;
    }

    Ello se utiliza un Tamaño personalizado objeto, porque Android Tamaño está disponible después de la API 21.

    public class Size {
    private int width;
    private int height;
    public Size(int width, int height) {
    this.width = width;
    this.height = height;
    }
    public int getHeight() {
    return height;
    }
    public int getWidth() {
    return width;
    }
    }

    Puede determinar el ancho y la altura de miras por la escucha de su sistema global de cambios de diseño y, a continuación, puede establecer las nuevas dimensiones. Esto también muestra cómo determinar mediante programación de la actividad de orientación:

    cameraPreviewLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
    //gets called after layout has been done but before display.
    cameraPreviewLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    boolean isActivityPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
    Size optimalCameraPreviewSize = CustomUtils.getOptimalPreviewSize(cameraPreview.getCameraSizes(), cameraPreviewLayout.getWidth(), cameraPreviewLayout.getHeight(), isActivityPortrait);
    if (optimalCameraPreviewSize != null) {
    LinearLayout.LayoutParams cameraPreviewLayoutParams = new LinearLayout.LayoutParams(optimalCameraPreviewSize.getWidth(), optimalCameraPreviewSize.getHeight());
    cameraPreviewLayout.setLayoutParams(cameraPreviewLayoutParams);
    }
    }
    });

    OriginalEl autor Galya

Dejar respuesta

Please enter your comment!
Please enter your name here