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
. - En 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 configurarTextureView
yPreview.SurfaceProvider
- Recuperar el elemento
SurfaceTexture
deTextureView
y configurarlo enPreview.SurfaceProvider
- Obtener el elemento
Surface
deSurfaceView
y configurarlo enPreview.SurfaceProvider
Si ocurre algo de lo anterior, Preview
deja de transmitir fotogramas a PreviewView
.
Cómo agregar un elemento PreviewView a tu diseño
En el siguiente ejemplo, se muestra un PreviewView
en un diseño:
<FrameLayout android:id="@+id/container"> <androidx.camera.view.PreviewView android:id="@+id/previewView" /> </FrameLayout>
Cómo solicitar un elemento CameraProvider
En el siguiente código, se muestra cómo solicitar 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); } }
Comprueba la disponibilidad de CameraProvider
Después de solicitar un elemento CameraProvider
, verifica que la inicialización se haya realizado correctamente 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 siguiente 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 CameraProvider
, haz lo siguiente:
- Crea un elemento
Preview
. - Especifica la opción de
LensFacing
deseada para la cámara. - Vincula la cámara y los casos de uso seleccionados al ciclo de vida.
- Conecta
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()
devuelve un objeto Camera
. Si quieres obtener más información para controlar la salida de la cámara, como el zoom y la exposición, consulta Salida de cámara.
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
CameraX PreviewView
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 para renderizar una transmisión de vista previa en el View
de destino:
PERFORMANCE
es el modo predeterminado.PreviewView
usa unSurfaceView
para mostrar la transmisión de video por Internet, pero recurre a unTextureView
en casos determinados.SurfaceView
posee una superficie de dibujo dedicada, que tiene más probabilidades de que el compositor de hardware interno lo implemente con una superposición de hardware, en especial cuando no hay otros elementos de la IU (botones "Me gusta") en la parte superior del video de vista previa. Al aplicar renderización con una superposición de hardware, los fotogramas 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 unTextureView
que, a diferencia deSurfaceView
, no tiene una superficie de dibujo dedicada. Como resultado, el video se renderiza con una compaginación para que se pueda mostrar. Durante este paso adicional, la aplicación puede realizar otras tareas de procesamiento, como las de escalar y rotar videos sin restricciones.
Usa PreviewView.setImplementationMode()
para seleccionar el modo de implementación adecuado para tu aplicación. Si el modo PERFORMANCE
predeterminado no es adecuado para tu aplicación, en la siguiente muestra de código se muestra cómo configurar el modo COMPATIBLE
:
Kotlin
// viewFinder is a PreviewView instance viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
Tipo de escala
Cuando la resolución de video de vista previa difiere de las dimensiones de tu PreviewView
de destino, el contenido de video debe ajustarse a la vista recortando o usando formato letterbox (conservando la relación de aspecto original). PreviewView
proporciona lo siguiente a ScaleTypes
para este fin:
FIT_CENTER
,FIT_START
yFIT_END
para el formato letterbox. El contenido de video completo se ajusta (aumenta o reduce) al tamaño máximo posible que se puede mostrar en elPreviewView
de destino. Sin embargo, aunque el fotograma del video completo es visible, es posible que parte de la pantalla esté en blanco. Según cuál de estos tres tipos de escala elijas, el fotograma se alineará con el centro, el inicio o el final de la vista de destino.FILL_CENTER
,FILL_START
yFILL_END
para recorte. Si un video no coincide con la relación de aspecto dePreviewView
, solo se verá una parte del contenido, pero llenará todo elPreviewView
.
El tipo de escala predeterminado que usa CameraX es FILL_CENTER
. Usa PreviewView.setScaleType()
para establecer el tipo de escala más apropiado para tu aplicación. En la siguiente muestra de código, se configura 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:
- Escala el video:
- Para los tipos de escala
FIT_*
, escala el video conmin(dst.width/src.width, dst.height/src.height)
. - Para los tipos de escala
FILL_*
, escala el video conmax(dst.width/src.width, dst.height/src.height)
.
- Para los tipos de escala
- Alinea el video ajustado con el destino
PreviewView
:- Para
FIT_CENTER/FILL_CENTER
, alinea el centro del video ajustado a escala con elPreviewView
de destino. - Para
FIT_START/FILL_START
, alinea el video ajustado y elPreviewView
de destino con respecto a la esquina superior izquierda de cada uno. - Para
FIT_END/FILL_END
, alinea el video ajustado y el destinoPreviewView
con respecto a la esquina inferior derecha de cada uno.
- Para
Por ejemplo, aquí hay un video de origen de 640 x 480 y un destino de PreviewView
de 1920 x 1080:
En la siguiente imagen, se muestra el proceso de escalamiento de FIT_START
, FIT_CENTER
y FIT_END
:
El proceso funciona de la siguiente manera:
- Escala el fotograma (manteniendo la relación de aspecto original) con
min(1920/640, 1080/480) = 2.25
para obtener un fotograma intermedio de 1440 x 1080. - Alinea el fotograma de 1440 x 1080 con el
PreviewView
de 1920 x 1080.- Para
FIT_CENTER
, alinea el fotograma con el centro de la ventanaPreviewView
. Las columnas de 240 píxeles inicial y final dePreviewView
están en blanco. - Para
FIT_START
, alinea el fotograma con el inicio (esquina superior izquierda) de la ventanaPreviewView
. Las columnas finales de 480 píxeles dePreviewView
están en blanco. - Para
FIT_END
, alinea el fotograma del video con el extremo (esquina inferior derecha) de la ventanaPreviewView
. Las columnas iniciales de 480 píxeles dePreviewView
están en blanco.
- Para
En la siguiente imagen, se muestra el proceso de escalamiento de FILL_START
, FILL_CENTER
y FILL_END
:
El proceso funciona de la siguiente manera:
- Escala el fotograma con
max(1920/640, 1080/480) = 3
para obtener un fotograma intermedio de 1920 x 1440 (que es más grande quePreviewView
). - Recorta el fotograma de 1920 x 1440 para que se ajuste a la ventana
PreviewView
de 1920 x 1080.- Para
FILL_CENTER
, recorta 1920 x 1080 del centro del video escalado de 1920 x 1440. Las 180 líneas de video superiores e inferiores no son visibles. - Para
FILL_START
, recorta 1920 x 1080 desde el inicio del video ajustado a 1920 x 1440. Las 360 líneas de video inferiores no son visibles. - Para
FILL_END
, recorta 1920 x 1080 desde el extremo del video escalado de 1920 x 1440. Las principales 360 líneas de video no son visibles.
- Para
Recursos adicionales
Para obtener más información sobre CameraX, consulta los siguientes recursos adicionales:
Codelab
Muestra de código