Let's say you want to implement a simple chat bubble like this, with RecyclerView ViewType and Kotlin:
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.
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
)
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 {
}
}
}
'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()
}
}
}