What's New

Implement a simple chat bubble with a button

Let's say you want to implement a simple chat bubble like this, with RecyclerView ViewType and Kotlin:

  1. When sending a message, fill in the key-value data in 'metaData' property which will be used for creating an UIView instance.

val metaData: HashMap<String, String> = hashMapOf()
metaData.apply {
    put("type", "msg_with_button")
    put("title", "Hi!")
    put("body", "This is a simple chat bubble with a button.")
    put("button_text", "Say Hello")
    put("button_action", "SayHello")
}

val params: TPMessageSendParams = TPMessageSendParams.Builder(channel,
        TPMessageSendParams.MessageType.TEXT,
        TPMessageSendParams.ContentType.TEXT)
        .setText(textMessage)
        .setMentions(mentionsUserIDs)
        .setParentMessageId(parentMessageId)
        .setMetaData(metaData)
        .setFileUrl()
        .setTranslationLanguages(translationLanguages)
        .build()
                
TalkPlus.sendMessage(params, 
    object : TalkPlus.CallbackListener<TPMessage>() {
        override fun onSuccess(tpMessage: TPMessage) { }
        override fun onFailure(errorCode: Int, exception: Exception) { }
})

You can enter up to 5 key-value pairs in data field. The maximum size of key is 128 characters and the maximum size of value is 1024 characters. Both key and value must be strings.

  1. Define a 'CardViewMessageModel' data class that contains data to be displayed on the screen.

data class CardViewMessageModel(
    var type: String,
    var title: String,
    var body: String,
    var button_text: String,
    var button_action: String
)
  1. Add a ViewType to RecyclerView Adapter class.

sealed class Item {
    object ChatBubble : Item()
    object AnotherItem : Item()
}

class MultiViewTypeAdapter(private val items: List<CardViewMessageModel>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    companion object {
        private const val VIEW_TYPE_CHAT_BUBBLE = 1
        private const val VIEW_TYPE_ANOTHER_ITEM = 2
    }

    override fun getItemViewType(position: Int): Int {
        return when (items[position]) {
            is Item.ChatBubble -> VIEW_TYPE_CHAT_BUBBLE
            is Item.AnotherItem -> VIEW_TYPE_ANOTHER_ITEM
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            VIEW_TYPE_CHAT_BUBBLE -> {
                val view = LayoutInflater.from(parent.context).inflate(R.layout.chat_bubble_item, parent, false)
                ChatBubbleViewHolder(view)
            }
            VIEW_TYPE_ANOTHER_ITEM -> {
                val view = LayoutInflater.from(parent.context).inflate(R.layout.another_item, parent, false)
                AnotherItemViewHolder(view)
            }
            else -> throw IllegalArgumentException("Invalid view type")
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is ChatBubbleViewHolder -> holder.bind()
            is AnotherItemViewHolder -> holder.bind()
        }
    }

    override fun getItemCount(): Int {
        return items.size
    }

    class ChatBubbleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val textTitle: TextView = itemView.findViewById(R.id.textTitle)
        private val textMessage: TextView = itemView.findViewById(R.id.textMessage)
        private val buttonSayHello: Button = itemView.findViewById(R.id.buttonSayHello)

        fun bind(cardViewMessageModel: CardViewMessageModel) {
            textTitle.text = cardViewMessageModel.title
            textMessage.text = cardViewMessageModel.body
            buttonSayHello.setOnClickListener {
                
            }
        }
    }
  1. 'messageReceived' method will be called whenever receiving a new message. At this method, call 'getData' method in 'TPMessage to get key-value data and then create an instance of 'CardViewMessageModel'.

TalkPlus.addChannelListener(channelId, object : ChannelListener { 
    override fun onMessageReceived(channel: TPChannel, tpMessage: TPMessage) {
        if (tpMessage.data.isNotEmpty()) {
            val metaData = tpMessage.data
            val cardViewMessageModel = CardViewMessageModel(
                type = metaData.type,
                title = metaData.title,
                body = metaData.body,
                button_text = metaData.button_text,
                button_action = metaData.button_action
            )
            chatMessages.add(cardViewMessageModel)
            chatAdapter.notifyItemInserted()
        }
    }
}

Last updated