Implementare un'anteprima

Quando aggiungi un'anteprima alla tua app, usa PreviewView, ovvero una View che può essere ritagliata, ridimensionata e ruotata per una visualizzazione corretta.

Quando la videocamera diventa attiva, l'anteprima dell'immagine viene riprodotta in streaming su una superficie all'interno di PreviewView.

Utilizzare la visualizzazione Anteprima

L'implementazione di un'anteprima per CameraX utilizzando PreviewView prevede i seguenti passaggi, illustrati nelle sezioni successive:

  1. Facoltativamente, configura una CameraXConfig.Provider.
  2. Aggiungi un elemento PreviewView al layout.
  3. Richiedi una ProcessCameraProvider.
  4. Al momento della creazione di View, controlla se è presente ProcessCameraProvider.
  5. Seleziona una videocamera e associa il ciclo di vita e i casi d'uso.

L'utilizzo di PreviewView presenta alcune limitazioni. Quando utilizzi PreviewView, non puoi eseguire nessuna delle seguenti operazioni:

  • Crea un SurfaceTexture da impostare su TextureView e Preview.SurfaceProvider.
  • Recupera SurfaceTexture da TextureView e impostalo su Preview.SurfaceProvider.
  • Scarica Surface da SurfaceView e impostala su Preview.SurfaceProvider.

Se si verifica una di queste condizioni, Preview interrompe lo streaming dei frame in PreviewView.

Aggiungere un elemento PreviewView al layout

Il seguente esempio mostra un elemento PreviewView in un layout:

<FrameLayout
    android:id="@+id/container">
        <androidx.camera.view.PreviewView
            android:id="@+id/previewView" />
</FrameLayout>

Richiedi un CameraProvider

Il codice seguente mostra come richiedere un CameraProvider:

Kotlin

import androidx.camera.lifecycle.ProcessCameraProvider
import com.google.common.util.concurrent.ListenableFuture

class MainActivity : AppCompatActivity() {
    private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider>
    override fun onCreate(savedInstanceState: Bundle?) {
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
    }
}

Java

import androidx.camera.lifecycle.ProcessCameraProvider
import com.google.common.util.concurrent.ListenableFuture

public class MainActivity extends AppCompatActivity {
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        cameraProviderFuture = ProcessCameraProvider.getInstance(this);
    }
}

Verifica la disponibilità di CameraProvider

Dopo aver richiesto un CameraProvider, verifica che l'inizializzazione sia riuscita al momento della creazione della vista. Il seguente codice mostra come eseguire questa operazione:

Kotlin

cameraProviderFuture.addListener(Runnable {
    val cameraProvider = cameraProviderFuture.get()
    bindPreview(cameraProvider)
}, ContextCompat.getMainExecutor(this))

Java

cameraProviderFuture.addListener(() -> {
    try {
        ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
        bindPreview(cameraProvider);
    } catch (ExecutionException | InterruptedException e) {
        // No errors need to be handled for this Future.
        // This should never be reached.
    }
}, ContextCompat.getMainExecutor(this));

Per un esempio della funzione bindPreview utilizzata in questo esempio, consulta il codice fornito nella prossima sezione.

Selezionare una videocamera e associare il ciclo di vita e i casi d'uso

Dopo aver creato e confermato il CameraProvider, procedi nel seguente modo:

  1. Crea un Preview.
  2. Specifica l'opzione LensFacing per la videocamera che ti interessa.
  3. Associa la videocamera selezionata e i casi d'uso al ciclo di vita.
  4. Collega Preview a PreviewView.

Il codice seguente mostra un esempio:

Kotlin

fun bindPreview(cameraProvider : ProcessCameraProvider) {
    var preview : Preview = Preview.Builder()
            .build()

    var cameraSelector : CameraSelector = CameraSelector.Builder()
          .requireLensFacing(CameraSelector.LENS_FACING_BACK)
          .build()

    preview.setSurfaceProvider(previewView.getSurfaceProvider())

    var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
}

Java

void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
    Preview preview = new Preview.Builder()
            .build();

    CameraSelector cameraSelector = new CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build();

    preview.setSurfaceProvider(previewView.getSurfaceProvider());

    Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview);
}

Tieni presente che bindToLifecycle() restituisce un oggetto Camera. Per ulteriori informazioni su come controllare l'output della videocamera, come lo zoom e l'esposizione, vedi Output videocamera.

A questo punto, hai completato l'implementazione dell'anteprima della fotocamera. Crea la tua app e verifica che l'anteprima venga visualizzata e funzioni come previsto.

Controlli aggiuntivi per PreviewView

CameraX PreviewView fornisce alcune API aggiuntive per configurare proprietà come:

Modalità di implementazione

PreviewView può utilizzare una delle seguenti modalità per eseguire il rendering di uno stream di anteprima sulla destinazione View:

  • PERFORMANCE è la modalità predefinita. PreviewView utilizza un elemento SurfaceView per visualizzare lo stream video, ma in determinati casi utilizza un valore TextureView. SurfaceView ha una superficie di disegno dedicata, che ha maggiori probabilità di essere implementato con un overlay hardware da parte del compositore hardware interno, soprattutto quando non ci sono altri elementi dell'interfaccia utente (come i pulsanti) nella parte superiore del video di anteprima. Grazie al rendering con una sovrapposizione hardware, i frame video evitano il percorso della GPU, il che può ridurre il consumo di energia e la latenza della piattaforma.

  • COMPATIBLE. In questa modalità, PreviewView utilizza un elemento TextureView che, a differenza di SurfaceView, non ha una superficie di disegno dedicata. Di conseguenza, il video viene visualizzato con una combinazione di elementi in modo da poter essere visualizzato. Durante questo passaggio aggiuntivo, l'applicazione può eseguire altre elaborazioni, ad esempio scalare e ruotare i video senza limitazioni.

Utilizza PreviewView.setImplementationMode() per selezionare la modalità di implementazione adatta alla tua applicazione. Se la modalità PERFORMANCE predefinita non è adatta alla tua applicazione, il seguente codice di esempio mostra come impostare la modalità COMPATIBLE:

Kotlin

// viewFinder is a PreviewView instance
viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE

Tipo di scala

Quando la risoluzione del video di anteprima è diversa dalle dimensioni dell'elemento PreviewView target, i contenuti video devono essere adattati alla visualizzazione ritagliando o modificando le proporzioni (mantenendo le proporzioni originali). PreviewView fornisce il seguente ScaleTypes a questo scopo:

  • FIT_CENTER, FIT_START e FIT_END per il letterbox. L'intero contenuto video viene ridimensionato (in alto o in basso) alla massima dimensione possibile visualizzabile nell'PreviewView di destinazione. Tuttavia, sebbene sia visibile l'intero frame del video, alcune parti dello schermo potrebbero essere vuote. A seconda di quali di questi tre tipi di scala scegli, il frame video verrà allineato al centro, all'inizio o alla fine della vista di destinazione.

  • FILL_CENTER, FILL_START, FILL_END per il ritaglio. Se un video non corrisponde alle proporzioni PreviewView, è visibile solo una parte dei contenuti, ma il video riempie l'intero PreviewView.

Il tipo di scala predefinito utilizzato da CameraX è FILL_CENTER. Utilizza PreviewView.setScaleType() per impostare il tipo di scala più appropriato per la tua applicazione. Il seguente esempio di codice imposta il tipo di scala FIT_CENTER:

Kotlin

// viewFinder is a PreviewView instance
viewFinder.scaleType = PreviewView.ScaleType.FIT_CENTER

La procedura per la visualizzazione di un video prevede i seguenti passaggi:

  1. Ridimensiona il video:
    • Per i tipi di scala FIT_*, scala il video con min(dst.width/src.width, dst.height/src.height).
    • Per i tipi di scala FILL_*, scala il video con max(dst.width/src.width, dst.height/src.height).
  2. Allinea il video in scala alla PreviewView di destinazione:
    • Per FIT_CENTER/FILL_CENTER, allinea al centro il video in scala e la destinazione PreviewView.
    • Per FIT_START/FILL_START, allinea il video in scala e la destinazione PreviewView rispetto all'angolo in alto a sinistra di ciascuno.
    • Per FIT_END/FILL_END, allinea il video in scala e la destinazione PreviewView rispetto all'angolo in basso a destra di ciascuno.

Ad esempio, ecco un video di origine in formato 640 x 480 e una destinazione in formato 1920 x 1080 PreviewView:

Immagine che mostra un video 640 x 480 rispetto a un&#39;anteprima 1920 x 1080

L'immagine seguente mostra il processo di scalabilità FIT_START / FIT_CENTER / FIT_END:

Immagine che mostra il processo di scalabilità FIT_START, FIT_CENTER e FIT_END

La procedura funziona nel seguente modo:

  1. Ridimensiona il frame video (mantenendo le proporzioni originali) con min(1920/640, 1080/480) = 2.25 per ottenere un fotogramma video intermedio di 1440 x 1080.
  2. Allinea il frame video 1440 x 1080 con l'PreviewView 1920 x 1080.
    • Per FIT_CENTER, allinea il frame del video al centro della finestra PreviewView. Le colonne iniziali e finali di 240 pixel della colonna PreviewView sono vuote.
    • Per FIT_START, allinea il frame del video all'inizio (angolo in alto a sinistra) della finestra PreviewView. Le colonne finali da 480 pixel della PreviewView sono vuote.
    • Per FIT_END, allinea il frame del video alla fine (angolo in basso a destra) della finestra di PreviewView. Le colonne iniziali da 480 pixel di PreviewView sono vuote.

L'immagine seguente mostra il processo di scalabilità FILL_START / FILL_CENTER / FILL_END:

Immagine che mostra il processo di ridimensionamento FILL_START, FILL_CENTER e FILL_END

La procedura funziona nel seguente modo:

  1. Ridimensiona il frame video con max(1920/640, 1080/480) = 3 per ottenere un frame video intermedio di 1920 x 1440, ovvero maggiore delle dimensioni di PreviewView.
  2. Ritaglia il frame video 1920x1440 per adattarlo alla finestra 1920x1080 PreviewView.
    • Per FILL_CENTER, ritaglia la dimensione 1920 x 1080 dal centro del video in scala 1920 x 1440. Le 180 righe superiore e inferiore del video non sono visibili.
    • Per FILL_START, ritaglia la dimensione 1920 x 1080 dall'inizio del video in scala 1920 x 1440. Le ultime 360 righe del video non sono visibili.
    • Per FILL_END, ritaglia la dimensione 1920 x 1080 dalla fine del video in scala 1920 x 1440. Le prime 360 righe del video non sono visibili.

Risorse aggiuntive

Per scoprire di più su CameraX, consulta le seguenti risorse aggiuntive.

Codelab

  • Introduzione a CameraX
  • Esempio di codice

  • Esempi di app CameraX