Message Template
Overview
A MessageTemplate provides you with the capability to define and customize both the structure and the behavior of the MessageBubble. It acts as a schema or design blueprint for the creation of a variety of MessageBubble components, allowing you to manage the appearance and interactions of MessageBubble within your application effectively and consistently.
Structure
The MessageBubble structure can typically be broken down into the following views:
-
Leading view: This is where the sender's avatar is displayed. It's typically on the left of the MessageBubble for messages from others and on the right for messages from the current user.
-
Header view: This displays the sender's name and is especially useful in group chats where multiple users are sending messages.
-
Content view: This is the core of the MessageBubble where the message content (text, images, videos, etc.) is displayed.
-
Bottom view: This view can be used to extend the MessageBubble with additional elements, such as link previews or a 'load more' button for long messages. It's typically placed beneath the Content view.
-
Footer view: This is where the timestamp of the message and its delivery or read status are displayed. It's located at the bottom of the MessageBubble.
Properties
MessageTemplate provides you with methods that allow you to alter various properties of the MessageBubble. These properties include aspects such as the type
and category
of a message, the appearance and behavior of the header, content, and footer sections of the message bubble,
-
Type
Using
setType()
you can set the type of CometChatMessage, This will map your MessageTemplate to the corresponding CometChatMessage. You can set the MessageTemplate Type using the following code snippet.messageTemplate.setType(UIKitConstants.MessageType.CUSTOM);
-
Category
Using
.setCategory()
you can set the category of a MessageTemplate. This will create a MessageTemplate with the specified category and link it with a CometChatMessage of the same category.Please refer to our guide on Message Categories for a deeper understanding of message categories.
messageTemplate.setCategory(UIKitConstants.MessageCategory.CUSTOM);
-
Header View
The .
setHeaderView()
method allows you to assign a custom header view to the MessageBubble. By default, it is configured to display the sender's name.messageTemplate.setHeaderView(Function3<Context, BaseMessage, UIKitConstants.MessageBubbleAlignment, View>);
-
Content View
The
.setContentView()
method allows you to assign a custom content view to the MessageBubble. By default, it displays the Text Bubble, Image Bubble, File Bubble, Audio Bubble, or Video Bubble, depending on the message type.messageTemplate.setContentView(Function3<Context, BaseMessage, UIKitConstants.MessageBubbleAlignment, View>);
-
Footer View
The
.setFooterView()
method allows you to assign a custom Footer view to the MessageBubble. By default, it displays the receipt and timestamp.messageTemplate.setFooterView(Function3<Context, BaseMessage, UIKitConstants.MessageBubbleAlignment, View>);
-
Bottom View
The
.setBottomView()
method allows you to assign a custom Bottom view to the MessageBubble.By defuault is has buttons such as link previews or a 'load more' button for long messages.messageTemplate.setBottomView(Function3<Context, BaseMessage, UIKitConstants.MessageBubbleAlignment, View>);
-
Bubble View
The
.setBubbleView()
method allows you to assign a custom Bubble view to the MessageBubble. By default, headerView, contentView, and footerView together form a message bubble.messageTemplate.setBubbleView(Function3<Context, BaseMessage, UIKitConstants.MessageBubbleAlignment, View>);
-
Options
The
.setOptions()
lets you set the list of actions that a user can perform on a message. This includes actions like reacting to, editing, or deleting a message.messageTemplate.setOptions(Function3<Context, BaseMessage, UIKitConstants.MessageBubbleAlignment, View>);
Customization
Let's dive into how you can use the properties of MessageTemplate to customize an existing template or add a new one to the MessageList component.
The First step is to fetch the list of existing templates when you want to modify or add to them. This can be done using the getAllMessageTemplates() method from the DataSource of the CometChatUIKit class.
List<CometChatMessageTemplate> messageTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
Existing Templates
You will need to first get the MessageTemplate object for the type of message you want to customize. You will be customizing the TextMessage Bubble here. The code snippet to get the Text MessageTemplate is as follows.
- Java
- Kotlin
List<CometChatMessageTemplate> messageTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
for(CometChatMessageTemplate template : messageTemplates){
if(template.getType().equals(UIKitConstants.MessageType.TEXT)){
// Code to customize text message template
}
}
val messageTemplates: List<CometChatMessageTemplate> = CometChatUIKit.dataSource.messageTemplates
for (template in messageTemplates) {
if (template.type == UIKitConstants.MessageType.TEXT) {
// Code to customize text message template
}
}
You will be using Messages Component for example here so to apply Template to Messages you will need to use MessageListConfiguration
. This is because the Set Templates function, which is used to apply the custom templates, belongs to the MessageList component.
You can apply MessageTemplates to Messages Component using the following code snippet.
- Java
- Kotlin
MessageListConfiguration configuration = new MessageListConfiguration();
List<CometChatMessageTemplate> messageTemplates = CometChatUIKit.getDataSource(getMessageTemplates()
for(CometChatMessageTemplate template : messageTemplates)
Log.e(TAG, "messageTemplate: Type = "+template.getType());
if(template.getType().equals(UIKitConstants.MessageType.TEXT))
// Code to customize text message template
}
}
configuration.setTemplates(messageTemplates);
cometChatMessages.setMessageListConfiguration(configuration);
val configuration = MessageListConfiguration.Builder(context).build()
val messageTemplates = CometChatUI.getAllMessageTemplates()
for (template in messageTemplates) {
Log.e(TAG, "messageTemplate: Type = ${template.type}")
if (template.type == UIKitConstants.MessageType.TEXT) {
// Code to customize text message template
}
}
configuration.setTemplates(messageTemplates)
cometChatMessages.setMessageListConfiguration(configuration)
Header view
The .setHeaderView()
method of MessageTemplate allows you to add custom views to the header of your message bubbles. In the example below, we will add a custom layout custom_txt_header_layout.xml
to the header view of every text message in the MessageList.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.cometchat.chatuikit.shared.views.CometChatAvatar.CometChatAvatar
android:id="@+id/avatar"
android:layout_width="20dp"
android:layout_height="20dp"
/>
</LinearLayout>
- Java
- Kotlin
template.setHeaderView(new MessagesViewHolderListener() {
@Override
public View createView(Context context, CometChatMessageBubble cometChatMessageBubble, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment) {
return getLayoutInflater().inflate(R.layout.custom_txt_header_layout, null);
}
@Override
public void bindView(Context context, View view, BaseMessage baseMessage, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment, RecyclerView.ViewHolder viewHolder, List<BaseMessage> list, int i) {
CometChatAvatar avatar = view.findViewById(R.id.avatar);
boolean isMyMsg = CometChatUIKit.getLoggedInUser().getUid().equals(baseMessage.getSender().getUid());
if(!isMyMsg)
avatar.setImage(baseMessage.getSender().getAvatar());
}
});
template.setHeaderView(object : MessagesViewHolderListener {
override fun createView(
context: Context,
cometChatMessageBubble: CometChatMessageBubble,
messageBubbleAlignment: UIKitConstants.MessageBubbleAlignment
): View {
return layoutInflater.inflate(R.layout.custom_txt_header_layout, null)
}
override fun bindView(
context: Context,
view: View,
baseMessage: BaseMessage,
messageBubbleAlignment: UIKitConstants.MessageBubbleAlignment,
viewHolder: RecyclerView.ViewHolder,
list: List<BaseMessage>,
i: Int
) {
val avatar = view.findViewById<CometChatAvatar>(R.id.avatar)
val isMyMsg = CometChatUIKit.loggedInUser.uid.equals(baseMessage.sender.uid)
if (!isMyMsg)
avatar.setImage(baseMessage.sender.avatar)
}
})
In this code, The createView() method inflates the 'custom_txt_header_layout.xml' as the header view for every message. The bindView() method allows you to bind your custom view, which will be called every time a ViewHolder for that message type is bound.
Content view
The .setContentView()
method of MessageTemplate allows you to add a custom view to the content of your message bubbles. In the example below, we will add a custom layout custom_message_content_layout.xml
to the content view of every text message in the MessageList.
- Java
- Kotlin
template.setContentView(new MessagesViewHolderListener() {
@Override
public View createView(Context context, CometChatMessageBubble cometChatMessageBubble, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment) {
return getLayoutInflater().inflate(R.layout.custom_message_content_layout, null);
}
@Override
public void bindView(Context context, View view, BaseMessage baseMessage, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment, RecyclerView.ViewHolder viewHolder, List<BaseMessage> list, int i) {
TextView txtMessage = view.findViewById(R.id.txt_msg);
if(baseMessage instanceof TextMessage)
txtMessage.setText(((TextMessage) baseMessage).getText());
}
});
template.setContentView(object : MessagesViewHolderListener {
override fun createView(
context: Context,
cometChatMessageBubble: CometChatMessageBubble,
messageBubbleAlignment: UIKitConstants.MessageBubbleAlignment
): View {
return LayoutInflater.from(context).inflate(R.layout.custom_message_content_layout, null)
}
override fun bindView(
context: Context,
view: View,
baseMessage: BaseMessage,
messageBubbleAlignment: UIKitConstants.MessageBubbleAlignment,
viewHolder: RecyclerView.ViewHolder,
list: List<BaseMessage>,
i: Int
) {
val txtMessage = view.findViewById<TextView>(R.id.txt_msg)
if (baseMessage is TextMessage) {
txtMessage.text = baseMessage.text
}
}
})
In this code, The createView() method inflates the 'custom_message_content_layout.xml' as the content view for every message. The bindView() method allows you to bind your custom view, which will be called every time a ViewHolder for that message type is bound.
Bottom View
The .setBottomView()
method of MessageTemplate allows you to add a custom button view to your message bubbles. In the example below, we will add a custom layout custom_message_bottom_layout.xml
to the bottom view of every text message in the MessageList.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<View
android:id="@+id/view_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/grey"
/>
<TextView
android:id="@+id/translate_message"
android:text="Translated Messages"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_height="wrap_content"/>
</LinearLayout>
- Java
- Kotlin
template.setBottomView(new MessagesViewHolderListener() {
@Override
public View createView(Context context, CometChatMessageBubble cometChatMessageBubble, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment) {
return getLayoutInflater().inflate(R.layout.custom_message_bottom_layout, null);
}
@Override
public void bindView(Context context, View view, BaseMessage baseMessage, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment, RecyclerView.ViewHolder viewHolder, List<BaseMessage> list, int i) {
TextView tvMessage = view.findViewById(R.id.translate_message);
View divider = view.findViewById(R.id.view_divider);
boolean isMyMsg = CometChatUIKit.getLoggedInUser().getUid().equals(baseMessage.getSender().getUid());
if(baseMessage instanceof TextMessage){
tvMessage.setText(((TextMessage) baseMessage).getText());
if(isMyMsg){
tvMessage.setGravity(Gravity.END);
divider.setBackgroundColor(Color.parseColor("#66FFFFFF"));
tvMessage.setTextColor(Color.parseColor("#66FFFFFF"));
}
}
}
});
template.setBottomView(object : MessagesViewHolderListener {
override fun createView(
context: Context,
cometChatMessageBubble: CometChatMessageBubble,
messageBubbleAlignment: UIKitConstants.MessageBubbleAlignment
): View {
return LayoutInflater.from(context).inflate(R.layout.custom_message_bottom_layout, null)
}
override fun bindView(
context: Context,
view: View,
baseMessage: BaseMessage,
messageBubbleAlignment: UIKitConstants.MessageBubbleAlignment,
viewHolder: RecyclerView.ViewHolder,
list: List<BaseMessage>,
i: Int
) {
val tvMessage = view.findViewById<TextView>(R.id.translate_message)
val divider = view.findViewById<View>(R.id.view_divider)
val isMyMsg = CometChatUIKit.loggedInUser.uid == baseMessage.sender.uid
if (baseMessage is TextMessage) {
tvMessage.text = baseMessage.text
if (isMyMsg) {
tvMessage.gravity = Gravity.END
divider.setBackgroundColor(Color.parseColor("#66FFFFFF"))
tvMessage.setTextColor(Color.parseColor("#66FFFFFF"))
}
}
}
})
In this code, The createView() method inflates the 'custom_message_bottom_layout.xml' as the bottom view for every message. The bindView() method allows you to bind your custom view, which will be called every time a ViewHolder for that message type is bound.
Footer View
The .setFooterView()
method of MessageTemplate allows you to add a footer view to your message bubbles. In the example below, we will add a custom layout custom_menu_layout.xml to the bottom view of every text message in the MessageList.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:id="@+id/card_reaction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/grey"
app:cardCornerRadius="20dp"
android:layout_margin="5dp"
>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_add_reaction"
android:padding="5dp"
/>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/card_reply"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/grey"
app:cardCornerRadius="20dp"
android:layout_margin="5dp"
>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_message"
android:padding="5dp"
/>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/card_forward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/grey"
app:cardCornerRadius="20dp"
android:layout_margin="5dp"
>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_reply"
android:padding="5dp"
/>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/card_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/grey"
app:cardCornerRadius="20dp"
android:layout_margin="5dp"
>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_bookmark"
android:padding="5dp"
/>
</androidx.cardview.widget.CardView>
</LinearLayout>
template.setFooterView(new MessagesViewHolderListener() {
@Override
public View createView(Context context, CometChatMessageBubble cometChatMessageBubble, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment) {
return getLayoutInflater().inflate(R.layout.custom_menu_layout, null);
}
@Override
public void bindView(Context context, View view, BaseMessage baseMessage, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment, RecyclerView.ViewHolder viewHolder, List<BaseMessage> list, int i) {
boolean isMyMsg = CometChatUIKit.getLoggedInUser().getUid().equals(baseMessage.getSender().getUid());
if(isMyMsg)
view.setVisibility(View.GONE);
}
});
In this code, The createView() method inflates the 'custom_menu_layout.xml' as the footer view for every message. The bindView() method allows you to bind your custom view, which will be called every time a ViewHolder for that message type is bound.
Bubble View
The .setBubbleView()
method of MessageTemplate allows you to add a bubble view to your message bubbles. In the example below, we will add a custom layout custom_message_content_layout.xml to the bubble view of every text message in the MessageList.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:id="@+id/card_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="20dp"
android:layout_margin="10dp"
app:cardElevation="5dp"
>
<TextView
android:id="@+id/txt_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
android:paddingEnd="10dp"
android:paddingStart="10dp"
android:textSize="20sp"
android:text="Message"
/>
</androidx.cardview.widget.CardView>
</RelativeLayout>
template.setBubbleView(new MessagesViewHolderListener() {
@Override
public View createView(Context context, CometChatMessageBubble cometChatMessageBubble, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment) {
return getLayoutInflater().inflate(R.layout.custom_message_content_layout, null);
}
@Override
public void bindView(Context context, View view, BaseMessage baseMessage, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment, RecyclerView.ViewHolder viewHolder, List<BaseMessage> list, int i) {
TextView textView = view.findViewById(R.id.txt_msg);
CardView cardView = view.findViewById(R.id.card_view);
boolean isMyMsg = CometChatUIKit.getLoggedInUser().getUid().equals(baseMessage.getSender().getUid());
if(baseMessage instanceof TextMessage)
textView.setText(((TextMessage) baseMessage).getText());
if(isMyMsg){
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)cardView.getLayoutParams();
params.addRule(RelativeLayout.ALIGN_PARENT_END);
cardView.setLayoutParams(params);
cardView.setCardBackgroundColor(getColor(R.color.purple_700));
textView.setTextColor(Color.WHITE);
}
}
});
Options List
The .setOptions()
method in the MessageTemplate allows you to customize the options that appear in the action sheet when a message is long-pressed. By default, CometChat UI Kit provides a set of options like "Reply", "Forward", "Edit", and "Delete".
However, if you wish to override or modify these options, you can use the .setOptions()
method and pass a list of CometChatMessageOption
. This list of options will replace the default set.
template.setOptions((context, baseMessage, group) -> {
List<CometChatMessageOption> optionList = new ArrayList<>();
CometChatMessageOption option1 = new CometChatMessageOption("delete","Delete",Color.RED, com.cometchat.chatuikit.R.drawable.cometchat_ic_delete_conversation,Color.RED,0,Color.WHITE,null);
optionList.add(option1);
CometChatMessageOption option2 = new CometChatMessageOption("forward","Forward",Color.BLACK,R.drawable.ic_reply,Color.GRAY,0,Color.WHITE,null);
optionList.add(option2);
CometChatMessageOption option3 = new CometChatMessageOption("Star","Mark as Favorite",Color.BLACK, com.cometchat.chatuikit.R.drawable.cometchat_heart_reaction,Color.GRAY,0,Color.WHITE,null);
optionList.add(option3);
return optionList;
});
New Templates
You can create an entirely new template for custom messages is one of the powerful features of CometChat's MessageTemplate.
First, let's see how to send a custom message:
CustomMessage customMessage = new CustomMessage("uid-1001", CometChatConstants.RECEIVER_TYPE_USER,"custom_buzz",new JSONObject().put("message_type","buzz_message"));
CometChatUIKit.sendCustomMessage(customMessage, new CometChat.CallbackListener<CustomMessage>() {
@Override
public void onSuccess(CustomMessage customMessage) {
Log.e(TAG, "onSuccess: Messages sending success = "+customMessage );
}
@Override
public void onError(CometChatException e) {
Log.e(TAG, "onError: Message Sending ",e );
}
});
Now, we'll create a new MessageTemplate to render this custom message in the MessageList:
List<CometChatMessageTemplate> messageTemplates = CometChatUIKit.getDataSource().getMessageTemplates();
CometChatMessageTemplate messageTemplate = new CometChatMessageTemplate()
.setCategory(CometChatConstants.CATEGORY_CUSTOM)
.setType("custom_buzz")
.setBubbleView(new MessagesViewHolderListener() {
@Override
public View createView(Context context, CometChatMessageBubble cometChatMessageBubble, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment) {
return getLayoutInflater().inflate(R.layout.custom_buzz_message_layout, null);
}
@Override
public void bindView(Context context, View view, BaseMessage baseMessage, UIKitConstants.MessageBubbleAlignment messageBubbleAlignment, RecyclerView.ViewHolder viewHolder, List<BaseMessage> list, int i) {
}
});
messageTemplates.add(messageTemplate);
In this code, replace "customType" with the same type as your custom message, and define your custom view in the setContentView() method.
This way, your custom message will be rendered in the MessageList using the custom view defined in your new MessageTemplate.