Listar contactos utilizando ArrayList con lenguaje Kotlin

En este artículo, explicaré como podemos utilizar un ArrayList (Collections) para listar los contactos al igual que lo hace WhatsApp por ejemplo, para dejar en claro que este ejemplo será estático lo que quiere decir es que no se podrá modificar en cuanto a persistencia de datos, para ello se utilizará el Adaptador ListView y a continuación veremos que es un Adaptador.

Pero qué es un Adaptador y para qué sirve...

Para poder trabajar directamente con Android Studio utilizando el lenguaje de Kotlin o Java es necesario utilizar el mecanismo que hace de puente entre nuestros datos y lo que queremos mostrar el cual se consideran las vistas contenidas dentro del componente ListView (también pueden ser  GridView o Spinner). Es cierto que para poder mantener la persistencia de los datos en este proceso es muy frecuente utilizar bases de datos para nuestras aplicaciones sean de escritorio, web o móviles, existen adaptadores específicos para este caso. La forma de trabajar habitual es hacer una consulta en una base de datos (comando SQL SELECT) y obtener un objeto Cursor con el resultado. Este objeto será pasado al adaptador para que lo recorra y cree tantas vistas como registros se hayan encontrado.

Pero que es es un Fragment y para qué sirve...

Para poder mejorar las vistas dentro de nuestra aplicación y dividirlas de modo tal que pueda pasarse como una paginación, se puede utilizar fragmentos, los cuales permiten que una aplicación se divida en subcomponentes para poder manejarlos de manera individual y combinarlos de distintas formas como si fuesen paneles. Es decir, en un dispositivo de pantalla pequeña (como un teléfono inteligente o tableta), una actividad típicamente llena toda una pantalla., mostrando los diversos puntos de vista que componen la interfaz de usuario de una aplicación. La actividad es esencialmente un contenedor. Sin embargo, cuando una actividad se muestra en un dispositivo de pantalla grande, como en una Tablet, la pantalla se vuelve mucho más grande y todos los elementos en una actividad deben estar dispuestos a hacer un uso completo de la pantalla más grande lo que resulta en cambios complejos a la jerarquía de visualización.

Otro control fundamental para el desarrollo de aplicaciones universales para Windows es el ListView. 

Ahora veremos un Wireframe de como se utilizará el ListView:

Muestra una lista de items(cada item de la lista puede estar compuesto por varios controles visuales) y nos permite interactuar con sus elementos (seleccionarlos, borrarlos, reordenarlos, entre otras acciones etc.)

Ahora crearemos un proyecto nuevo llamado Agenda, accederá a una ArrayList que se creará de manera estática y el adaptador dentro de un ListView se encargará de cargarlo. El cual se mostrará como en el siguiente diseño.


Comenzaremos abriendo nuestro Android Studio, y comenzamos creando nuestro proyecto utilizaremos el lenguaje Kotlin por estar actualmente disponible.


Vamos a incorporar algunas librerias dentro de nuestro archivo .gradle de la aplicación, para poder manejar fragments, imagenes circulares, y además el efecto de carga utilizando Glide. Para ello nos dirigimos a Gradle Scripts > build.gradle (Module: Agenda.app) abrimos con doble clic y agregamos las siguientes librerías, recordemos que a medida que pase el tiempo las versiones de estas librerías irán cambiando y deberás actualizar de manera constante de acuerdo a este suceso. Lo colocamos dentro de dependencies
    

    //Por Ing. Dick Díaz Delgado

    implementation 'androidx.fragment:fragment:1.0.0'
    implementation 'androidx.navigation:navigation-fragment:2.0.0'
    implementation 'androidx.navigation:navigation-ui:2.0.0'
    implementation 'com.github.bumptech.glide:glide:4.10.0'
    implementation 'de.hdodenhof:circleimageview:3.1.0'

Crearemos ahora un fragmento para incorporarlo dentro de nuestra actividad y este sea capaz de insertarlo dentro del Adaptador de nuestro ListView. Primero creamos una nueva carpeta llamada fragment, con el clic derecho sobre la carpeta colocaremos el nombre de nuestro package unificado, y seleccionamos New > Package.




Ahora hacemos clic derecho sobre la carpeta creada fragment, y seleccionamos New > Fragment > Fragment (Blank), la nombraremos ContactoFragment. y junto a este archivo Kotlin se creará una vista Xml.




Dentro de nuestra actividad principal agregaremos la etiqueta FragmentContainerView, el cual integraremos al momento de instanciarlo dentro de nuestro código kotlin de la actividad principal.



El identificador que le colocaremos será fragmento_principal.

Ahora editaremos el xml creado de nuestro ContactoFragment.kt, añadire un ListView como en la siguiente imagen:


Como nuestro fragment se encuentra de forma independiente, es decir no está incluido dentro de ningún lugar, lo incluiremos dentro de nuestra Actividad principal. Para eso utilizaremos el siguiente código.
    //Por Ing. Dick Díaz Delgado    

    val fragmentManager = supportFragmentManager
    fragmentManager.beginTransaction().replace(R.id.fragmento_principal, ContactoFragment(), "ContactoFragment").commit()


La creación del diseño para nuestro adaptador es importante, es por ello que agregaremos un nuevo layout.xml a nuestro proyecto con el nombre de list_item_contacto.



El código XML para el diseño de nuestra aplicación es el siguiente.



Ahora añadiremos una clase adaptador el cual permitirá utilizando una clase llamada Contacto (la cual crearemos luego) obtener la información según el Wireframe presentado inicialmente. Para mantener un orden crearemos primero el package adapter dentro crearemos la clase ContactoAdapter.








Vamos a cambiar todo el contenido de nuestro ContactoAdapter por el siguiente:
    

    //Por Ing. Dick Díaz Delgado    
    
    class ContactoAdapter(private val context: Context, private val dataSource: ArrayList<Contacto>) : BaseAdapter() {
       
       //Obtenermos diseño para que este se cree al momento de llamar al adapter
       private val inflater: LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

       //Obtener la cantidad de Elementos del ListView
       override fun getCount(): Int {
           return dataSource.size
       }

       //Obtener el elemento según la posición
       override fun getItem(position: Int): Any {
           return dataSource[position]
       }

       //Obtener el identificador según la posición 
       override fun getItemId(position: Int): Long {
           return position.toLong()
       }
       
       //Creamos el método getView para la vista de nuestro Adapter
       override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
          
          //Obtenemos la vista y la colocamos a una variable para poder utilizarla e inicializar
          val rowView = inflater.inflate(R.layout.list_item_contacto, parent, false)

          //Obtener el elemento imagen
          val imagen = rowView.findViewById(R.id.iv_avatar) as CircleImageView

          //Obtener el elemento nombre
          val nombre = rowView.findViewById(R.id.tv_name) as TextView

          //Obtener el elemento cargo
          val cargo = rowView.findViewById(R.id.tv_title) as TextView

          //Obtener el elemento empresa
          val empresa = rowView.findViewById(R.id.tv_company) as TextView

          //Instanciamiento del objeto contacto de la clase Contacto
          val contacto = getItem(position) as Contacto

          //Asignación de valores a los elementos según corresponda el indice
          nombre.text = contacto.nombre
          cargo.text = contacto.cargo
          empresa.text = contacto.empresa
          Glide.with(context).load(contacto.imagen).into(imagen);

          return rowView
    
       }

    }


Ahora debemos crear la clase Contacto que permitirá el instanciamiento para la obtención de los elementos mencionados anteriormente, para ello crearé una carpeta dentro de la carpeta java, llamada clase dentro del cual añadiremos la clase Contacto. El código es el siguiente


Anteriormente se creo el ContactoFragment.kt, lo que haré es modificar la estructura de este archivo a través del siguiente código:


    

    //Por Ing. Dick Díaz Delgado    

    import android.os.Bundle
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.BaseAdapter
    import android.widget.ListView
    import androidx.fragment.app.Fragment
    import app.avanzado.agenda.R
    import app.avanzado.agenda.adapter.ContactoAdapter
    import app.avanzado.agenda.clase.Contacto

    class ContactoFragment : Fragment() {

        override fun onCreate(savedInstanceState: Bundle?) {
        
            super.onCreate(savedInstanceState)

        }

        override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {

            val root: View = inflater.inflate(R.layout.fragment_contacto, container, false)

            var mContactoList = root.findViewById<View>(R.id.contacto_list) as ListView
            var mContactoAdapter : BaseAdapter

            val contactos: ArrayList<Contacto> = ArrayList()

            contactos.add(
                contactos.size,
                Contacto("1", "Hugh Larie", "Médico Cirujano", "EsSalud", "https://noverbal.es/uploads/blog/rostro-de-un-criminal.jpg")
            )

            contactos.add(
                contactos.size,
                Contacto("2", "Taylor Swift", "Cantante", "Big Machine Records Republic Records", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhgsWm5w1W9vHMQoOzsqmWM4fsygzsCvp2JxPg4qiz5YrBMA4oJcxG-PHJVVbgmAfXLs8&usqp=CAU")
            )

            contactos.add(
                contactos.size,
                Contacto("3", "Dick Díaz Delgado", "Docente", "Universidad César Vallejo", "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9nfewnrUuM58saEtKcUxU3ka3PbHcUIvGARn_ae5A0BQ7rIe0TvnaaexLH6TN0XJ6_QSQXO9Uom2Y4AOK5dZ4VS2OjCDoJ2vFh1j3Lqfj8KvipLtAlqx3RfZLswaWoqFAMJdkTd9V3zY/s95-pf/1.png")
            )

            contactos.add(
                contactos.size,
                Contacto("4", "Daniel Radcliffe", "Actor", "Warner Bross", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTy8KH0Wk2Znad97x3FMEIrVoK4qGToyayolIbInRs1MvGSIWOxaAugGQ-Wnkxbn8n2MjY&usqp=CAU")
            )

            contactos.add(
                contactos.size,
                Contacto("5", "Sandra Bullock", "Actriz", "Netflix", "https://www.univision.com/proxy/api/cached/picture?href=https%3A%2F%2Fst1.uvnimg.com%2Fad%2Fb4%2Fb82e44cb4e8f84cc0c7950cc6d1b%2F05b2d773e5aa4aeb95dcfd3971cb8730&width=214&height=320&ratio_width=303&ratio_height=303&resize_option=Fill%20Area")
            )

            contactos.add(
                contactos.size,
                Contacto("6", "Angela Aguilar", "Cantante", "El Financiero", "https://laopinion.com/wp-content/uploads/sites/3/2021/09/GettyImages-1174354474-e1631743859271.jpg?quality=80&strip=all&w=1200")
            )

            // Inicializar el adaptador con la fuente de datos.
            mContactoAdapter = ContactoAdapter(requireActivity(), contactos)

            mContactoList.adapter = mContactoAdapter
            setHasOptionsMenu(true);

            return root;

        }

    }

El resultado sería el siguiente:


Esto es uno de los ejemplos sencillo, puedes utilizar una base de datos que puedes acceder a través de una url o json, como también una NoSQL, como en el caso de Firebase RealTime o Firestore. Te dejo el link donde podrás descargar el proyecto desde este enlace.

Espero haya sido de gran ayuda este artículo.


Comentarios

Entradas populares de este blog

Practica de Diagrama de Flujo Intermedio - Resueltos

Personaliza tus reportes PDF desde PHP con la librería FPDF

Ejercicios Básicos para aprender a programar en Android Studio [Java y Kotlin]