Creando una Aplicación Android que responda ante comandos de Voz mediante Inteligencia Artificial y Machine Learning – Parte 4

En este Post continuaré con la creación de mi aplicación Android, en la parte anterior llamada Creando una Aplicación Android que responda ante comandos de Voz mediante Inteligencia Artificial y Machine Learning – Parte 3, hice la creación del layout para el Chat en donde se muestran los mensajes del usuario y de la Inteligencia Artificial, en este Parte entraré netamente a trabajar con el código Kotlin, vamos con el Post.

Partes

Fuente: Vecteezy

En la Parte 2 de este tutorial agregue un List View que será el contenedor los mensajes entre el usuario y la inteligencia artificial

<ListView
        android:layout_width="match_parent"
        android:id="@+id/contenedor_chat"
        android:layout_weight="2"
        android:divider="#fff"
        android:background="#d2d2d2"
        android:layout_marginBottom="12dp"
        android:layout_height="0dp"/>

Para poder mostrar los mensajes en el List View necesito crear un Adapter, esto lo haré a continuación

Adapter para los Mensajes

Creo un archivo Kotlin llamado MensajesAdapter.kt este archivo lo creo en app > java > com.example.iapostresapp > MensajesAdapter.kt

/app
├── /manifests
├── /java
    ├── /com.example.iapostresapp
        ├── MainActivity.kt 
        ├── MensajesAdapter.kt // Creo este archivo 
├── /java (generated)
├── /res
├── /res (generated)
/Gradle Scripts

Abro el archivo MensajesAdapter.kt e importo los siguientes elementos

import android.app.Activity
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView

Antes de crear la clase para el MensajesAdapter, creo una clase llamada Mensaje que me permitirá renderizar un mensaje independientemente en el chat

class Mensaje(val text: String, val mensajeEntrante: Boolean)

Ahora creo el adaptador para los mensajes, este se llama MensajesAdapter

class MensajesAdapter(private var context: Context) : BaseAdapter() { 

    // Acá va el Contenido para el MensajesAdapter  

}

Dentro del Adapter voy declarar una variable privada llamada mensajes esta variable va contener una Lista de Datos (Array) en donde le paso la clase Mensaje que había creado anteriormente antes de crear el MensajesAdapter

Luego creo una función con el nombre agregarMensaje, en ella notifico algún cambio que se realice en el List View de manera asíncrona

class MensajesAdapter(private var context: Context) : BaseAdapter() {

    // Variable privada mensajes 
    private var mensajes: ArrayList<Mensaje> = ArrayList()

    // Función agregarMensaje 
    fun agregarMensaje(message: Mensaje) {
        this.mensajes.add(message)
        notifyDataSetChanged()
    }

}

La función agregarMensaje trabajará con la función getView que crearé a continuación

Ahora voy a crear la función o método llamado getView, en el voy a crear la variable mensajesInflater y en su interior hago uso de LAYOUT_INFLATER_SERVICE que me permite inflar los elementos y recursos del diseño del Chat, también creo una variable llamada mensajeActual en donde obtengo la posición de cada mensaje.

Luego Renderizo los mensajes entrantes y salientes que se producen en el espacio dentro del Chat, en esto creo una variable llamada vistaModificada en donde verifico si hay un mensaje entrante y utilizo el layout llamado mensaje_entrante para mostrar el mensaje entrante y si hay un mensaje saliente utilizo el layout mensaje_saliente para mostrar el mensaje saliente, estos 2 layouts los he crado en la Parte 3 de este Tutorial, después de terminar la creación del Adapter, luego llamo al ID que le he puesto a los 2 layouts mensaje_entrante y mensaje_saliente, a estos les daré el mismo ID, los llamare cuerpo_mensaje. Por último devuelvo la vista con los cambios en los mensajes del Chat

class MensajesAdapter(private var context: Context) : BaseAdapter() {

    // Variable privada mensajes 
    private var mensajes: ArrayList<Mensaje> = ArrayList() 
    
    // Función agregarMensaje
    fun agregarMensaje(message: Mensaje) {
        this.mensajes.add(message)
        notifyDataSetChanged()
    } 

    // Método getView 
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val mensajesInflater: LayoutInflater = context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        val mensajeActual = getItem(position)

        // Renderizo los mensajes Salientes y entrantes del Chat
        val vistaModificada = if (mensajeActual.mensajeEntrante)
            mensajesInflater.inflate(R.layout.mensaje_entrante, null)
        else
            mensajesInflater.inflate(R.layout.mensaje_saliente, null)

        // Cambio el cuerpo del Nuevo mensaje 
        val cuerpoMensaje = vistaModificada.findViewById(R.id.cuerpo_mensaje) as TextView
        cuerpoMensaje.text = mensajeActual.text

        // Muestro la lista con los cambios realizados en los mensajes
        return vistaModificada
    }

}

Para terminar mi MensajesAdapter, voy a usar 3 métodos nativos del Adapter, el primero es getItem que me permite obtener la posición de cada mensaje del Chat, el segundo método es getItemId que me permite obtener el indice de un mensaje del Chat y el tercer método es getCount que me devuelve la cantidad o número de mensajes en el Chat

class MensajesAdapter(private var context: Context) : BaseAdapter() {

    // Variable privada mensajes 
    private var mensajes: ArrayList<Mensaje> = ArrayList() 
    
    // Función agregarMensaje
    fun agregarMensaje(message: Mensaje) {
        this.mensajes.add(message)
        notifyDataSetChanged()
    } 

    // Método getView 
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val mensajesInflater: LayoutInflater = context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        val mensajeActual = getItem(position)

        // Renderizo los mensajes Salientes y entrantes del Chat
        val vistaModificada = if (mensajeActual.mensajeEntrante)
            mensajesInflater.inflate(R.layout.mensaje_entrante, null)
        else
            mensajesInflater.inflate(R.layout.mensaje_saliente, null)

        // Cambio el cuerpo del Nuevo mensaje 
        val cuerpoMensaje = vistaModificada.findViewById(R.id.cuerpo_mensaje) as TextView
        cuerpoMensaje.text = mensajeActual.text

        // Muestro la lista con los cambios realizados en los mensajes
        return vistaModificada
    }

    // Obtengo la posición de cada mensaje del Chat 
    override fun getItem(position: Int): Mensaje {
        return mensajes[position]
    }

    // Obtengo el índice de un mensaje del Chat 
    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    // Me Devuelve la cantidad o número de Mensajes en el Chat 
    override fun getCount(): Int {
        return mensajes.size
    }

}

Con esto tengo listo mi Adaptador o Adapter MensajesAdapter para los mensajes entrantes y salientes.

Ten Paciencia, lo que quiero es que entiendas todo el proceso de como crear la aplicación y no llenarte el capitulo de mucho contenido porque te puedes marear y no tendrás un óptimo aprendizaje. 

Nota(s)

  • En el siguiente capitulo entraré netamente a trabajar con codigo Kotlin en donde creare los métodos en sus archivos correspondientes para darle la correcta funcionalidad a la aplicación.

 

Síguenos en nuestras Redes Sociales para que no te pierdas nuestros próximos contenidos.