Creación de pantalla de previsualización de fotos con Jetpack Compose
Clase 28 de 33 • Curso de Android: Integración de APIs nativas
Resumen
Desarrollar una aplicación para Android eficiente y amigable implica aprovechar al máximo las capacidades que ofrece Jetpack Compose. Uno de los procesos fundamentales es darle al usuario la opción de previsualizar una imagen después de haberla capturado, ofreciéndole la alternativa de guardar o cancelar dicha acción. Dominar este procedimiento permite crear una interfaz fluida y centrada en la experiencia del usuario.
¿Cómo preparar la pantalla de previsualización con Jetpack Compose?
Preparar una pantalla de previsualización sencilla y eficaz requiere utilizar Composables específicos. Para comenzar, se crea un Composable
denominado photo preview screen, el cual recibe:
- Un arreglo de bytes (byte array) que representa la imagen tomada.
- Dos funciones lambda: una acción llamada
onSave
para guardar la foto y una acciónonCancel
para descartarla.
Esta vista incluye:
- Una columna que contiene un Box, mostrando la imagen previamente convertida a Image bitmap usando una extensión creada.
- Un Row que alberga dos íconos claramente identificables, uno para cancelar y otro para guardar la imagen mostrada.
Toda esta configuración facilita que el usuario tome decisiones rápidas e intuitivas sobre qué hacer con su imagen recién capturada.
¿Cómo gestionar el estado desde el ViewModel?
La manera óptima para manejar la información y la interacción con la UI es utilizando un ViewModel en combinación con un estado observable:
- Obtén el estado del ViewModel a través de
collectAsState
, observando la disponibilidad de la imagen tomada. - Según el estado del ViewModel y la disponibilidad del preview, se muestra la pantalla con la imagen capturada o la pantalla de la cámara.
Ejemplo práctico de cómo invocar la pantalla de previsualización:
val uiState by viewModel.uiState.collectAsState()
val previewPhoto by viewModel.previewPhoto.collectAsState()
if(uiState.previewMode && previewPhoto != null){
PhotoPreviewScreen(
photoBytes = previewPhoto,
onSave = { viewModel.action(Intent.SavePhoto) },
onCancel = { viewModel.action(Intent.CancelPreview) }
)
}else{
CameraScreen(onPhotoTaken = { imageProxy ->
// Lógica para rotar imagen aquí
})
}
Esta estructura clara asegura que siempre se visualice la pantalla correcta, mejorando significativamente la usabilidad.
¿Cómo rotar correctamente las imágenes capturadas?
La rotación es un proceso crítico para reflejar correctamente las imágenes capturadas desde la cámara. Dado que la imagen inicialmente llega en orientación de 90 grados, debe realizarse un ajuste utilizando una matriz de rotación:
- Se extrae la rotación directa desde
imageProxy.imageInfo.rotationDegrees
. - Se crea un bitmap rotado usando una matriz para ajustar apropiadamente la imagen capturada.
Código de ejemplo para rotar la imagen correctamente:
val matrix = Matrix().apply{
postRotate(imageProxy.imageInfo.rotationDegrees.toFloat())
}
val rotatedBitmap = imageProxy.toBitmap().let{
Bitmap.createBitmap(it,0,0,it.width,it.height,matrix,true)
}
viewModel.action(CameraIntent.TakingPicture(rotatedBitmap))
Siguiendo estos pasos, aseguras que las fotos capturadas se visualicen correctamente desde cualquier dispositivo Android.
Integración en la navegación de la aplicación
La pantalla de captura y previsualización debe estar cuidadosamente integrada en la configuración principal de navegación:
- Reemplaza la pantalla previa de cámara (
cameraScreen
) por la nueva creada (cameraScreenRoot
). - Valida mediante el emulador que todo sea funcional, permitiendo tanto la captura como la revisión de fotos.
Recuerda que estos ajustes son elementales para garantizar que la navegación cumpla con las expectativas del usuario y el estándar de desarrollo actual.
Reto adicional para practicar: No olvides realizar el proceso de solicitud de permisos como lo realizaste anteriormente con la pantalla MapScreen, verificando los detalles del repositorio si tienes dudas sobre esta implementación. ¡Ánimo!