Custom Views en Android: Extendiendo una vista existente
Antonio Leiva

En el v铆deo de hoy te explico qu茅 son las Custom Views o vistas personalizadas, y qu茅 necesitas saber para implementarlas.

Vamos a ver a fondo un ejemplo que a pesar de ser relativamente sencillo, requiere de bastantes pasos para entenderlo por completo.

Te explicar茅:

  • Qu茅 es una Custom View
  • C贸mo definir una Custom View que extienda de una View ya existente
  • C贸mo modificar su comportamiento
  • C贸mo incluirla en nuestros dise帽os
  • C贸mo a帽adir propiedades personalizadas directamente en XML
  • C贸mo recuperar esos valores por c贸digo

Aqu铆 tienes el v铆deo:

Ya hemos visto a lo largo de los videos anteriores que tenemos una serie de vistas proporcionadas por el framework de Android que nos ayudan a crear las pantallas con la estructura que nosotros necesitemos, pero habr谩 ocasiones en las que esas vistas no se ajusten a lo que necesitemos o porque nos interese agrupar un conjunto de vistas para crear una nueva. Vamos a necesitar crear lo que se denomina Custom Views (vistas personalizadas).

Lo que queremos hacer es un par de vistas personalizadas. La primera vista es una imagen.

La imagen anterior es un grid, dividida por filas y columnas, donde le hemos dicho que haya 3 elementos por fila, o sea, tres columnas. Por tanto en funci贸n de como sea la pantalla estos elementos ser谩n mas anchos o mas estrechos y no queremos que la imagen crezca mas en alto que en ancho o vice versa, queremos que lo haga de forma proporcional.

Vamos a crear una Custom view con ImageView un poco variado. Esta es una de las opciones que tenemos cuando creamos una vista personalizada que nos basemos en una vista que ya existe y le adaptemos cosas. El b谩sico y esencial ser铆a basarnos en la vista View que es como un lienzo en blanco, y luego modificar ciertas cosas. Nosotros vamos a ir a un nivel de abstracci贸n un poco mas arriba y vamos a sobrescribir el comportamiento habitual que tiene el ImageView.

Lo primero que haremos es crear un archivo que se va a llamar AspectRatioImageView yendo a:

No olvidar que la carpeta se llamara distinto dependiendo del nombre que se le haya dado al momento de crear el proyecto en los pasos anteriores.

ahora crearemos una clase con el nombre del archivo y lo que tenemos que hacer es que extienda de ImageView, es decir, que coja todas las propiedades y funcionalidad de ImageView y que la podamos usar en nuestra clase. Se extiende colocando dos puntos y seguido el nombre de la clase que deseamos extender:

Esto nos va a obligara llamar a un constructor padre, es decir, la forma en la que definimos como se construye este objeto o sino crear varios constructores. Una cosa importante es que cuando estamos trabajando con la librer铆a de AppCompat, que por defecto la vas a usar siempre si estas usando una de las plantillas de Android Studio. En vez de extender de la variante del framework de Android Studio utilicemos la de AppCompat.

Nos recomendara que es lo mas sencillo para usar los constructores y quedar铆a de la siguiente manera. Con esto ya nos da todas las propiedades que puede necesitar un ImageView o en general cualquier vista cuando la estamos creando. La principal y si la creamos por c贸digo es el contexto (context) que es b谩sicamente una acumulaci贸n de informaci贸n que le sirve a la vista para ver como pintarse, que tema usar, este tipo de cosas . El resto solo son necesarias si estamos creando esta vista desde XML. Cuando se crea la vista por el XML algunas de las cosas que definimos se pasaran por el constructor.

Luego de esto tenemos que definir cual va hacer el AspectRatio que vamos a utilizar. Lo podemos poner como una propiedad privada de tipo Float e iniciaremos con el valor de 1. El tipo Float ser铆a un numero en coma flotante que lo que quiere decir es que puede tener decimales, de tal forma que el AspectRatio pueda ser 1×1.5, esto quiere decir que por cada 1 de ancho necesita 1.5 de alto.
Lo siguiente que necesitar铆amos hacer para nuestra imagen es sobrescribir onMeasure (sin centrarte en el c贸digo que esta escrito sino en las cosas que puedas hacer). El d铆a que necesitas hacer algo parecido vas necesitar informarte mucho mejor en como funcionan las Custom View porque dependen mucho de lo que quieras hacer, tambi茅n conlleva matem谩tica implicada, es relativamente complejo.

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

Lo que har铆amos es sobrescribir la funci贸n onMeasure, esta funci贸n se llama cuando estamos pintando una pantalla y queremos saber cual es el tama帽o final que va a tener esa vista, para dec铆rselo a las vistas padre, pasara por este m茅todo, adem谩s nos dar谩 informaci贸n de cual es la configuraci贸n que tiene esa vista, las vistas padre, definir谩 cierta informaci贸n para que puedas definir con mayor fiabilidad cual es el tama帽o que le vas a dar a tus vista. A veces podr谩s utilizar estos argumentos que vienen por parametro en la funci贸n onMeasure, los cuales est谩n relacionados con el Match_Parent o el Wrap_Content o si le asignamos un tama帽o especifico nos vendr谩 identificado aqu铆 tambi茅n. Dejaremos que la vista coja el tama帽o que le corresponder铆a en funci贸n de todo el resto de configuraci贸n y luego modificarle la altura con el AspectRatio en comparaci贸n con el ancho. As铆 que vamos a coger el tama帽o de la propia property de la clase measureWidth, como tambi茅n el alto. Estos son la altura y la anchura una vez se ha medido y luego de esto tenemos que comprobar que si ambos valores son iguales a cero, hara que el codigo de nuestra funci贸n no se ejecute porque todav铆a no se ha terminado de medir la vista y no tenemos los datos para calcular los datos en funci贸n del ancho.

class AspectRatioImageView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {
    var ratio: Float = 1f

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var width = measuredWidth
        var height = measuredHeight

        if (width == 0 && height == 0) {
            return
        }
    }
}

El siguiente paso es comprobar si alguna de las dos no es cero, cual de ellas es distinto de cero. Porque por ejemplo si el ancho es cero quiere decir que no tiene informaci贸n suficiente para calcularla y que lo que estamos intentando es calcular la anchura en funci贸n de la altura, si es el caso contrario y tenemos el ancho debemos calcular en funcion del ancho el alto.

class AspectRatioImageView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {
    private var ratio: Float = 1f

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var width = measuredWidth
        var height = measuredHeight

        if (width == 0 && height == 0) {
            return
        }

        if(width > 0){
            height = (width*ratio).toInt()
        } else if(height > 0){
            width = (height/ratio).toInt()
        }
    }
}

Ya al final para decirle que hemos decido modificar el alto y el ancho con respecto a lo que nos hab铆a dado nuestra clase padre WidthMeasureSpec tenemos que llamar a setMeasuredDimension() y como argumentos le pasamos el width y height.

setMeasuredDimension(width, height)

Ahora nos vamos a ir a la activity_main.xml y borraremos todas las vistas que teniamos, luego vamos a帽adir una View de tipo AspectRatioImageView. Para a帽adir nuestra vista personalizada tendremos que hacerlo por codigo. Al escribir las iniciales de la vista que queremos llamar el auto completador nos mostrara cual es, de la siguiente manera.

Quiz谩 tambi茅n te interese…

Los 7 mejores cursos online para aprender Android desde cero en 2021

Los 7 mejores cursos online para aprender Android desde cero en 2021

No hay que ser un genio para darse cuenta de que el sector del desarrollo de aplicaciones m贸viles est谩 en auge y cada vez m谩s gente busca aprender Android para iniciarse en esta profesi贸n. Atra铆dos, c贸mo no, por la posibilidad de obtener un empleo estable, (muy) bien...

0 comentarios

Enviar un comentario

Los datos personales que proporciones a trav茅s de este formulario quedar谩n registrados en un fichero de Antonio Leiva Gordillo, con el fin de gestionar los comentarios que realizas en este blog. La legitimaci贸n se realiza a trav茅s del consentimiento de la parte interesada. Si no se acepta, no podr谩s comentar en este blog. Los datos que proporciona solo se utilizan para evitar el correo no deseado y no se usar谩n para nada m谩s. Puede ejercer los derechos de acceso, rectificaci贸n, cancelaci贸n y oposici贸n en contacto@devexperto.com.

Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *

Acepto la pol铆tica de privacidad *