¿Cómo personalizar la cámara en una aplicación Android?
Personalizar la interfaz de usuario (UI) de la cámara en una aplicación Android es una habilidad esencial para los desarrolladores que buscan ofrecer experiencias únicas e innovadoras a sus usuarios. En esta clase, nos enfocaremos en crear la actividad de la cámara, añadiendo todos los componentes gráficos que hemos desarrollado en lecciones anteriores para que puedas crear tu propia experiencia de usuario personalizada.
¿Cómo inicializar la actividad de la cámara?
Para comenzar a personalizar la cámara, primero debemos inicializar las variables básicas y asegurarnos de que nuestro entorno está adecuadamente configurado. Aquí te dejo una estructura básica del código necesario:
var previewWidth =320var previewHeight =240// Verificar que el Lens Engine esté creadoif(lensEngine !=null){val size = lensEngine.getDisplayDimensions()if(size !=null){ previewHeight = size.height
previewWidth = size.width
}}
Este fragmento de código proporciona un punto de partida configurando las dimensiones de previsualización y validando que el motor de lente (Lens Engine) está correctamente inicializado.
¿Cómo verificar la configuración del contexto y ajustar el layout?
Para que el layout de la cámara sea el más apto posible en términos de tamaño y orientación, verifica que el contexto está en modo retrato y ajusta tu configuración:
Este proceso asegura que el layout de la cámara sea dinámico y se adapte automáticamente al modo de orientación del dispositivo, lo cual es crucial para ofrecer una visualización óptima.
¿Cómo calcular y ajustar el ratio de la vista?
El cálculo del ratio entre el ancho y la altura es vital para garantizar que la vista de la cámara y el marco no se salgan de los límites. Aquí un ejemplo básico:
Al mantener estos ratios, se garantiza que la vista de la cámara no exceda el área de visualización disponible, brindando una experiencia de usuario fluida y agradable.
¿Cómo implementar un overlay gráfico y motor de lente?
Una vez configuradas las dimensiones y ratios, es fundamental implementar un overlay gráfico y un motor de lente para finalizar la personalización de la cámara:
Este xml muestra cómo integrar un LensEnginePreview y un GraphicOverlay, elementos esenciales para mostrar y superponer gráficos sobre la vista de la cámara.
A lo largo de este proceso, hemos creado una base sólida para personalizar la interfaz de cámara de una aplicación Android. Este conocimiento no solo enriquece tus habilidades de desarrollo, sino que también mejora el valor de las aplicaciones que desarrollas. Sigue aprendiendo y explorando nuevas posibilidades para llevar tus capacidades al siguiente nivel. ¡Adelante!
Sería interesante que en este curso se tomaran el tiempo para detallar ciertos conceptos. Por ejemplo, en esta clase, los cálculos realizados para que el foco de la cámara y el rostro "no se salgan de los límites", convierten la experiencia en un reto de copiar y pegar código; al menos para mí.
Sin archivos o enlaces que permitan al estudiante reforzar el tema o la clase .. solo una observación.
Estoy de acuerdo en tu punto.
Hasta este momento siento que los conceptos han sido bastante superficiales, ya que no se ha profundizado en detallar el porqué algún parámetro, etc.
Estoy totalmente de acuerdo, en si el curso se vuelve vacio de contenido, cuesta entender!! se vuelve tedioso y vacio
LensEnginePreview
package com.sandoval.hselfiecamera.cameraimport android.content.Contextimport android.content.res.Configurationimport android.util.AttributeSetimport android.util.Logimport android.view.SurfaceHolderimport android.view.SurfaceViewimport android.view.ViewGroupimport com.huawei.hms.common.size.Sizeimport com.huawei.hms.mlsdk.common.LensEngineimport com.sandoval.hselfiecamera.overlay.GraphicOverlayimport java.io.IOExceptionclassLensEnginePreview(context:Context,attrs:AttributeSet?):ViewGroup(context, attrs){private val mContext:Context= context
private val mSurfaceView:SurfaceViewprivatevarmStartRequested:BooleanprivatevarmSurfaceAvailable:BooleanprivatevarmLensEngine:LensEngine?=nullprivatevarmOverlay:GraphicOverlay?=null init { mStartRequested =false mSurfaceAvailable =false mSurfaceView =SurfaceView(context)// Nuestra vista va a pedir un callback para agregar el lentethis.addView(mSurfaceView)} override fun onLayout(changed:Boolean,left:Int,top:Int,right:Int,bottom:Int){var previewWidth =320var previewHeight =240if(mLensEngine !=null){ val size:Size?= mLensEngine!!.displayDimensionif(size !=null){ previewHeight = size.height previewWidth = size.width}}if(mContext.resources.configuration.orientation==Configuration.ORIENTATION_PORTRAIT){ val tmp = previewWidth
previewWidth = previewHeight
previewHeight = tmp
} val viewWidth = right - left
val viewHeight = bottom - top
val childWidth:Int val childHeight:Intvar childXOffset =0var childYOffset =0 val widthRatio = viewWidth.toFloat()/ previewWidth.toFloat() val heightRation = viewHeight.toFloat()/ previewHeight.toFloat()if(widthRatio > heightRation){ childWidth = viewWidth
childHeight =(previewHeight.toFloat()* heightRation).toInt() childYOffset =(childHeight - viewHeight)/2}else{ childWidth =(previewHeight.toFloat()* heightRation).toInt() childHeight = viewHeight
childXOffset =(childWidth - viewWidth)/2}for(i in0 until this.childCount){getChildAt(i).layout(-1* childXOffset,-1* childYOffset, childWidth - childXOffset, childHeight - childYOffset
)}try{startIfReady()}catch(e:IOException){Log.e("Error","No se pudo iniciar la camara")}} @Throws(IOException::class) fun start(lensEngine:LensEngine?,overlay:GraphicOverlay?){ mOverlay = overlay
start(lensEngine)} @Throws(IOException::class) fun start(lensEngine:LensEngine?){if(lensEngine ==null){stop()} mLensEngine = lensEngine
if(mLensEngine !=null){ mStartRequested =true// Vamos a crear una funcion que nos va a decir//si la camara esta lista}} fun stop(){if(mLensEngine !=null){ mLensEngine!!.close()}} fun release(){if(mLensEngine !=null){ mLensEngine!!.release() mLensEngine =null}} @Throws(IOException::class) fun startIfReady(){if(mStartRequested && mSurfaceAvailable){ mLensEngine!!.run(mSurfaceView.holder)if(overlay !=null){ val size:Size= mLensEngine!!.displayDimension val min:Int= size.width.coerceAtMost(size.height) val max:Int= size.width.coerceAtLeast((size.height))if(Configuration.ORIENTATION_PORTRAIT== mContext.resources.configuration.orientation){ mOverlay!!.setCameraInfo(min, max, mLensEngine!!.lensType)}else{ mOverlay!!.setCameraInfo(max, min, mLensEngine!!.lensType)} mOverlay!!.clear()} mStartRequested =false}}private inner classSurfaceCallback:SurfaceHolder.Callback{ override fun surfaceChanged(holder:SurfaceHolder?,format:Int,width:Int,height:Int){} override fun surfaceDestroyed(holder:SurfaceHolder?){ mSurfaceAvailable =false} override fun surfaceCreated(holder:SurfaceHolder?){ mSurfaceAvailable =truetry{startIfReady()}catch(e:IOException){Log.e("Error: ","No pudimos iniciar la camra $e")}}}}