2012-07-04 12 views
23

Ho un'applicazione Android che deve mostrare a schermo intero un'anteprima della telecamera indipendentemente dalla dimensione dell'anteprima fornita da getSupportedPreviewSizes() senza distorsioni. Mi aspetto che ritagli l'anteprima di una certa quantità in altezza o in larghezza, ma questo non mi riguarda. Il motivo per cui cerco di farlo è che alcune fotocamere Android (ad esempio la fotocamera frontale Samsung Galaxy SII) non restituiscono anteprime con le stesse proporzioni del display e pertanto devono essere allungate e tagliate.Adattamento di un'anteprima della telecamera a SurfaceView più grande del display

E 'possibile far crescere completamente l'anteprima della telecamera in una vista più grande della dimensione del display? È possibile far crescere SurfaceView più grande delle dimensioni dei pixel di anteprima restituite semplicemente impostando i parametri di layout della vista di superficie su match_parent, ma ciò provoca una distorsione in qualche direzione e solo fino all'anteprima del display. Ciò sembra indicare che l'anteprima al di fuori del display è impossibile e che l'hardware (o il sistema operativo) limita tale comportamento.

C'è l'another question sull'argomento, ma quella domanda afferma che non è possibile creare un SurfaceView superiore alle dimensioni dello schermo, che è falso, come ho trovato con la registrazione. Tuttavia, ciò che sembra essere il caso è che l'anteprima della fotocamera tuttavia non può crescere fino alle dimensioni di un enorme SurfaceView.

Il mio tentativo:

Ho un layout di relativo, al suo interno un FrameLayout, e all'interno di tale creo un SurfaceView. La larghezza dell'intero layout relativo è impostata al di sotto di 635 dpi, che è ~ il doppio della dimensione dello schermo del dispositivo. Il FrameLayout corrisponde a questo dimensionamento e così fa il SurfaceView (aggiunto a livello di codice in seguito)

<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> 

Il seguente è il codice che ottiene e imposta le dimensioni dell'anteprima. Qui voglio far espandere l'anteprima della fotocamera per riempire l'intero FrameLayout (raddoppiando la larghezza dello schermo). La vista si presenta e si distrugge in modo totalmente normale, quindi sto rimuovendo il codice non correlato a questa particolare domanda perché distrae dalla domanda essenziale e il mio tentativo di espandere facilmente e semplicemente la vista a dimensioni più grandi del display.

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

io sono preoccupato del fatto che l'unico modo per avere successo in questo sforzo è quello di rendere in qualche modo a una superficie openGL, ma questo apparently potrebbe essere troppo lento a colori. È anche un problema se l'anteprima della fotocamera può semplicemente essere allungata e ritagliata.

Grazie in anticipo a qualsiasi tentativo di soluzione.

+0

Potrebbe pls di u inserire codice ur OnCreate(). o dove chiami il metodo setcontentview() –

+0

Perché sei curioso di quel codice? Era piuttosto semplice e bastava impostare la visualizzazione del contenuto sull'XML che ho condiviso sopra. –

+0

ok quindi penso che espandere una vista oltre il gestore di finestre non sia possibile, sto anche cercando lo zoom in una sezione di video ma usando tutte le viste di superficie e video personalizzate non ottengo nessuna, il video non è ritagliato oltre la dimensione –

risposta

12

Ok, so che è molto tardi come risposta, ma è possibile. Di seguito è riportato il codice dall'esempio di Android SDK. Per vedere il resto del codice per implementare questo download i campioni SDK Android e andare 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); 
     } 
    } 
} 
} 

questo codice ha lo scopo di adattare l'anteprima alla dimensione più piccola (che non rovinare il rapporto aspcect) e centro per avere barre nere sull'altra dimensione. Ma se si capovolge il > per essere < invece si otterrà quello che vuoi. Es:

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