2012-07-04 12 views
23

Tengo una aplicación de Android que necesita una pantalla completa para una vista previa de cámara independientemente del tamaño de vista previa proporcionado por getSupportedPreviewSizes() sin distorsión. Espero que esto recorte la vista previa en cierta cantidad, ya sea en la altura o el ancho, pero esto no me concierne. La razón por la que intento hacerlo es porque ciertas cámaras Android (por ejemplo, la cámara frontal Samsung Galaxy SII) no devuelven ninguna vista previa con la misma relación de aspecto que la pantalla y, por lo tanto, deben estirarse y recortarse.Adaptar una vista previa de cámara a SurfaceView más grande que la pantalla

¿Es posible hacer crecer completamente la vista previa de la cámara a una vista mayor que el tamaño de visualización? Es posible hacer crecer SurfaceView más grande que las dimensiones de píxeles de vista previa devueltas simplemente configurando los parámetros de diseño de la vista de superficie para match_parent, pero esto produce distorsión en alguna dirección y solo es posible hasta que la vista previa llene la pantalla. Esto parece indicar que la vista previa fuera de la pantalla es imposible, y el hardware (u OS) limita dicho comportamiento.

Hay another question sobre el tema, pero esa pregunta afirma que no es posible crear un SurfaceView mayor que las dimensiones de la pantalla, que es falso, como he encontrado con el registro. Sin embargo, lo que parece ser el caso es que la vista previa de la cámara no puede crecer al tamaño completo de una enorme SurfaceView.

mi intento:

que tienen una disposición relativa, en su interior una FrameLayout, y dentro de ese creo un SurfaceView. El ancho de toda la disposición relativa se establece a continuación en 635 pb, que es ~ el doble del tamaño de la pantalla del dispositivo. El FrameLayout coincide con este tamaño y también lo hace el SurfaceView (añadido mediante programación más adelante)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/camera_activity_layout" 
    android:layout_width="635dp" 
    android:layout_height="match_parent" > 

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

</RelativeLayout> 

El siguiente es el código que obtiene y establece el tamaño de vista previa. Aquí quiero hacer que la vista previa de la cámara se expanda para llenar todo el FrameLayout (el doble del ancho de la pantalla). La vista se muestra y se destruye totalmente normalmente, así que elimino el código que no está relacionado con esta pregunta en particular porque distrae de la pregunta esencial y mi intento de aumentar la vista de manera simple y sencilla a un tamaño mayor que el de la pantalla.

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

Me preocupa que la única manera de tener éxito en esta tarea es hacer de alguna manera a una superficie OpenGL, pero esto apparently podría ser demasiado lento a todo color. También es un dolor si la vista previa de la cámara simplemente se puede estirar y recortar.

Gracias de antemano a cualquier intento de solución.

+0

Podría usted publicar su código oncreate(). o donde llama al método setcontentview() –

+0

¿Por qué siente curiosidad por ese código? Era bastante básico, y simplemente configuraba la vista de contenido para el xml que compartí arriba. –

+0

ok, así que creo que expandir una vista más allá del administrador de ventanas no es posible, también estoy buscando ampliar una sección de video pero usando toda la vista de superficie y la vista de video personalizada no obtengo ninguna, el video no está recortado más allá del tamaño –

Respuesta

12

Ok, sé que esto es muy tarde como respuesta, pero es posible. A continuación se muestra el código de la muestra del SDK de Android. Para ver el resto del código para implementar esta descarga las muestras SDK de Android e ir a 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); 
     } 
    } 
} 
} 

este código está destinada a ser la vista previa a la dimensión más pequeña (que no lo hace estropear la relación aspcect) y centro para tener barras negras en la otra dimensión. Pero si voltea el > para que sea <, obtendrá lo que quiera. Ejemplo:

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