Cuando agregues una vista previa a tu app, usa PreviewView
, que es una View
que se puede recortar, escalar y rotar para mostrarse correctamente.
La vista previa de la imagen se transmite a una superficie dentro de PreviewView
cuando se activa la cámara.
Cómo usar PreviewView
La implementación de una vista previa de CameraX con PreviewView
implica los siguientes pasos, que se explican en secciones posteriores:
- De manera opcional, configura un
CameraXConfig.Provider
. - Agrega un elemento
PreviewView
a tu diseño. - Solicita un elemento
ProcessCameraProvider
. - Durante la creación de
View
, comprueba la presencia deProcessCameraProvider
. - Selecciona una cámara y vincula el ciclo de vida y los casos de uso.
El uso de PreviewView
tiene algunas limitaciones. Cuando usas PreviewView
, no puedes hacer nada de lo siguiente:
- Crear un elemento
SurfaceTexture
para configurar enTextureView
yPreview.SurfaceProvider
- Recuperar el elemento
SurfaceTexture
deTextureView
y configurarlo enPreview.SurfaceProvider
- Obtener el elemento
Surface
deSurfaceView
y configurarlo enPreview.SurfaceProvider
Si se produce alguno de estos problemas, Preview
detendrá la transmisión de marcos a PreviewView
.
Cómo agregar un elemento PreviewView a tu diseño
En el siguiente ejemplo, se muestra un elemento PreviewView
en un diseño:
<FrameLayout android:id="@+id/container"> <androidx.camera.view.PreviewView android:id="@+id/previewView" /> </FrameLayout>
Solicita un elemento CameraProvider
En el siguiente código, se muestra cómo solicitar un elemento 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); } }
Comprueba la disponibilidad de CameraProvider
Después de solicitar un elemento CameraProvider
, verifica que se realice correctamente la inicialización cuando se cree la vista. El siguiente código muestra cómo hacer esto:
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));
Para ver un ejemplo de la función bindPreview
que se usa en esta muestra, consulta el código proporcionado en la próxima sección.
Selecciona una cámara y vincula el ciclo de vida y los casos de uso
Una vez que hayas creado y confirmado el elemento CameraProvider
, haz lo siguiente:
- Crea un elemento
Preview
. - Especifica la opción de cámara
LensFacing
deseada. - Vincula la cámara seleccionada y los casos de uso al ciclo de vida.
- Conecta el elemento
Preview
aPreviewView
.
En el siguiente código, se muestra un ejemplo:
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); }
Ten en cuenta que bindToLifecycle()
muestra un objeto Camera
. Consulta esta guía a fin de obtener más información para controlar la salida de la cámara, como el zoom y la exposición.
Ya terminaste de implementar la vista previa de la cámara. Compila tu app y confirma que la vista previa aparezca en ella y funcione como lo deseas.
Controles adicionales para PreviewView
El elemento PreviewView
de CameraX proporciona algunas API adicionales para configurar propiedades, como las siguientes:
- El modo de implementación para renderizar transmisiones de vista previa
- El tipo de escala de la imagen de vista previa
Modo de implementación
PreviewView
puede usar uno de los siguientes modos a fin de renderizar una transmisión de vista previa en la View
de destino:
PERFORMANCE
es el modo predeterminado.PreviewView
usa unaSurfaceView
para mostrar la transmisión de video por Internet, pero recurre a unaTextureView
en algunos casos.SurfaceView
tiene una superficie de dibujo dedicada, que tiene más probabilidades de implementarse con una superposición de hardware por parte del compositor de hardware interno, en especial cuando no hay otros elementos de la IU (como botones) sobre el video de vista previa. Cuando se renderiza con una superposición de hardware, los marcos de video evitan una ruta de GPU, lo que puede reducir el consumo de energía y la latencia de la plataforma.Modo
COMPATIBLE
: En este modo,PreviewView
usa unaTextureView
que, a diferencia deSurfaceView
, no tiene una superficie de dibujo dedicada. Por lo tanto, el video se renderiza mediante fusiones de modo que se pueda mostrar. Durante este paso adicional, la aplicación puede realizar un procesamiento adicional, como ajustar y rotar videos sin restricción.
Usa PreviewView.setImplementationMode()
a fin de seleccionar el modo de implementación adecuado para tu aplicación. Si el modo PERFORMANCE
predeterminado no resulta útil para tu aplicación, la siguiente muestra de código indica cómo configurar el modo COMPATIBLE
:
Kotlin
// viewFinder is a PreviewView instance viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
Tipo de escala
Cuando la resolución del video de vista previa difiera de las dimensiones de tu PreviewView
objetivo, el contenido de video deberá ajustarse a la vista, ya sea mediante recortes o formato letterbox (lo que mantiene la relación de aspecto original). A tal fin, PreviewView
proporciona los siguientes ScaleTypes
:
FIT_CENTER
,FIT_START
yFIT_END
para el formato letterbox. Se ajusta el contenido completo del video (ya sea un aumento o una disminución) al tamaño máximo posible que se puede mostrar en laPreviewView
objetivo. Sin embargo, mientras se vea todo el marco de video, es posible que algunas partes de la pantalla queden en blanco. Según cuál de estos tres tipos de escala elijas, el marco de video se alineará con el centro, el inicio o el final de la Vista objetivo.FILL_CENTER
,FILL_START
yFILL_END
para los recortes. Si un video no coincide con la relación de aspecto de laPreviewView
, solo una parte del contenido es visible, pero el video abarca toda laPreviewView
.
El tipo de escala predeterminado que usa CameraX es FILL_CENTER
. Usa PreviewView.setScaleType()
a fin de establecer el tipo de escala más adecuado para tu aplicación. En la siguiente muestra de código, se establece el tipo de escala FIT_CENTER
:
Kotlin
// viewFinder is a PreviewView instance viewFinder.scaleType = PreviewView.ScaleType.FIT_CENTER
El proceso para mostrar un video consta de los siguientes pasos:
- Ajusta el video:
- Para los tipos de escala
FIT_*
, ajusta el video conmin(dst.width/src.width, dst.height/src.height)
. - Para los tipos de escala
FILL_*
, ajusta el video conmax(dst.width/src.width, dst.height/src.height)
.
- Para los tipos de escala
- Alinea el video ajustado con la
PreviewView
objetivo:- Para
FIT_CENTER/FILL_CENTER
, centra el video ajustado y laPreviewView
objetivo. - Para
FIT_START/FILL_START
, alinea el video ajustado y laPreviewView
objetivo respecto de la esquina superior izquierda de cada uno. - Para
FIT_END/FILL_END
, alinea el video ajustado y laPreviewView
objetivo respecto de la esquina inferior derecha de cada uno.
- Para
Por ejemplo, este es un video fuente de 640 x 480 y una PreviewView
objetivo de 1920 x 1080:
En la siguiente imagen, se muestra el proceso de ajuste de FIT_START
, FIT_CENTER
y FIT_END
:
El proceso funciona de la siguiente manera:
- Ajusta el marco de video (manteniendo la relación de aspecto original) con
min(1920/640, 1080/480) = 2.25
para obtener un marco de video intermedio de 1440 x 1080. - Alinea el marco de video de 1440 x 1080 con la
PreviewView
de 1920 x 1080.- Para
FIT_CENTER
, alinea el marco de video con el centro de la ventana de laPreviewView
. Las columnas de los 240 píxeles iniciales y finales de laPreviewView
están en blanco. - Para
FIT_START
, alinea el marco de video con el inicio (esquina superior izquierda) de la ventana de laPreviewView
. Las columnas de los 480 píxeles finales de laPreviewView
están en blanco. - Para
FIT_END
, alinea el marco de video con el final (esquina inferior derecha) de la ventana de laPreviewView
. Las columnas de los 480 píxeles iniciales delPreviewView
están en blanco.
- Para
En la siguiente imagen, se muestra el proceso de ajuste de FILL_START
, FILL_CENTER
y FILL_END
:
El proceso funciona de la siguiente manera:
- Ajusta el marco de video con
max(1920/640, 1080/480) = 3
para obtener un marco de video intermedio de 1920 x 1440 (que es más grande que el tamaño de laPreviewView
). - Recorta el marco de video de 1920 x 1440 de modo que se ajuste a la ventana de la
PreviewView
de 1920 x 1080.- Para
FILL_CENTER
, recorta 1920 x 1080 desde el centro del video ajustado de 1920 x 1440. Las 180 líneas superiores e inferiores del video no se verán. - Para
FILL_START
, recorta 1920 x 1080 desde el inicio del video ajustado de 1920 x 1440. Las 360 líneas inferiores del video no se verán. - Para
FILL_END
, recorta 1920 x 1080 desde el final del video ajustado de 1920 x 1440. Las 360 líneas superiores del video no se verán.
- Para
Recursos adicionales
Para obtener más información sobre CameraX, consulta los siguientes recursos adicionales:
Codelab
Muestra de código