cometchat-android-v5-customization
Customize CometChat components beyond theming — custom message templates, DataSource decorators, event listeners, and custom view slots.
What it does
Companion skills:
cometchat-android-v5-componentsprovides the component catalog;cometchat-android-v5-themingcovers visual styling;cometchat-android-v5-extensionscovers the extension architecture.
Purpose
This skill teaches how to customize CometChat components beyond what theming provides. It covers custom message templates, the DataSource/DataSourceDecorator pattern, ChatConfigurator, event listeners, and custom view slots.
Use this skill when
- "Customize the message list"
- "Add a custom message bubble"
- "Listen to message events"
- "Add a custom action to message options"
- "Filter conversations"
Do not use this skill when
- Changing colors/fonts → use
cometchat-android-v5-theming - Enabling a packaged feature → use
cometchat-android-v5-features - Setting up init/login → use
cometchat-android-v5-core
1. CometChatMessageTemplate
Templates define how message bubbles are rendered. Each template maps a message type + category to custom views.
Java:
CometChatMessageTemplate template = new CometChatMessageTemplate()
.setType(CometChatConstants.MESSAGE_TYPE_TEXT)
.setCategory(CometChatConstants.CATEGORY_MESSAGE)
.setContentView(new MessagesViewHolderListener() {
@Override
public View createView(Context context, CometChatMessageBubble messageBubble,
UIKitConstants.MessageBubbleAlignment alignment) {
// Return your custom view
return LayoutInflater.from(context).inflate(R.layout.custom_text_bubble, null);
}
@Override
public void bindView(Context context, View createdView, BaseMessage message,
UIKitConstants.MessageBubbleAlignment alignment,
RecyclerView.ViewHolder holder, List<BaseMessage> messageList,
int position) {
// Bind data to your custom view
TextView textView = createdView.findViewById(R.id.customText);
textView.setText(((TextMessage) message).getText());
}
})
.setOptions((context, baseMessage, group) -> {
// Return custom message options (long-press menu)
List<CometChatMessageOption> options = new ArrayList<>();
options.add(new CometChatMessageOption("custom_action", "Custom Action",
R.drawable.ic_custom, () -> { /* handle click */ }));
return options;
});
// Apply to message list
messageList.setTemplates(Collections.singletonList(template));
Kotlin:
val template = CometChatMessageTemplate()
.setType(CometChatConstants.MESSAGE_TYPE_TEXT)
.setCategory(CometChatConstants.CATEGORY_MESSAGE)
.setContentView(object : MessagesViewHolderListener() {
override fun createView(context: Context, messageBubble: CometChatMessageBubble,
alignment: UIKitConstants.MessageBubbleAlignment): View {
return LayoutInflater.from(context).inflate(R.layout.custom_text_bubble, null)
}
override fun bindView(context: Context, createdView: View, message: BaseMessage,
alignment: UIKitConstants.MessageBubbleAlignment,
holder: RecyclerView.ViewHolder, messageList: List<BaseMessage>,
position: Int) {
val textView = createdView.findViewById<TextView>(R.id.customText)
textView.text = (message as TextMessage).text
}
})
.setOptions { context, baseMessage, group ->
listOf(CometChatMessageOption("custom_action", "Custom Action",
R.drawable.ic_custom) { /* handle click */ })
}
messageList.setTemplates(listOf(template))
Template view slots
| Slot | Method | Description |
|---|---|---|
bubbleView | setBubbleView(MessagesViewHolderListener) | Entire message bubble |
headerView | setHeaderView(MessagesViewHolderListener) | Above the bubble |
contentView | setContentView(MessagesViewHolderListener) | Inside the bubble |
bottomView | setBottomView(MessagesViewHolderListener) | Below the content, inside bubble |
footerView | setFooterView(MessagesViewHolderListener) | Below the bubble |
statusInfoView | setStatusInfoView(MessagesViewHolderListener) | Status info area |
replyView | setReplyView(MessagesViewHolderListener) | Reply preview above bubble |
2. CometChatMessageOption
Custom actions in the message long-press menu.
Java:
CometChatMessageOption option = new CometChatMessageOption(
"bookmark", // unique ID
"Bookmark", // title
R.drawable.ic_bookmark, // icon
() -> { // onClick
// Handle bookmark action
}
);
3. DataSource and DataSourceDecorator
The DataSource interface defines how messages are rendered and what options are available. DataSourceDecorator wraps an existing DataSource to add or modify behavior without replacing it.
Java:
public class CustomDataSource extends DataSourceDecorator {
public CustomDataSource(DataSource dataSource) {
super(dataSource);
}
@Override
public List<CometChatMessageOption> getTextMessageOptions(Context context,
BaseMessage baseMessage, Group group, AdditionParameter additionParameter) {
List<CometChatMessageOption> options = super.getTextMessageOptions(context,
baseMessage, group, additionParameter);
// Add custom option
options.add(new CometChatMessageOption("translate", "Translate",
R.drawable.ic_translate, () -> { /* translate */ }));
return options;
}
}
Kotlin:
class CustomDataSource(dataSource: DataSource) : DataSourceDecorator(dataSource) {
override fun getTextMessageOptions(context: Context, baseMessage: BaseMessage,
group: Group?, additionParameter: AdditionParameter): List<CometChatMessageOption> {
val options = super.getTextMessageOptions(context, baseMessage, group, additionParameter).toMutableList()
options.add(CometChatMessageOption("translate", "Translate",
R.drawable.ic_translate) { /* translate */ })
return options
}
}
Register via ChatConfigurator
Java:
ChatConfigurator.enable(dataSource -> new CustomDataSource(dataSource));
Kotlin:
ChatConfigurator.enable { dataSource -> CustomDataSource(dataSource) }
4. Event system
CometChat provides event classes for reacting to chat events. Register listeners with a unique tag.
CometChatMessageEvents
Java:
CometChatMessageEvents.addListener("unique-tag", new CometChatMessageEvents() {
@Override
public void ccMessageSent(BaseMessage baseMessage, int status) {
// Message sent
}
@Override
public void onTextMessageReceived(TextMessage textMessage) {
// Text message received
}
@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
// Reaction added
}
});
// Remove when done
CometChatMessageEvents.removeListener("unique-tag");
Kotlin:
CometChatMessageEvents.addListener("unique-tag", object : CometChatMessageEvents() {
override fun ccMessageSent(baseMessage: BaseMessage, status: Int) {
// Message sent
}
override fun onTextMessageReceived(textMessage: TextMessage) {
// Text message received
}
override fun onMessageReactionAdded(reactionEvent: ReactionEvent) {
// Reaction added
}
})
// Remove when done
CometChatMessageEvents.removeListener("unique-tag")
CometChatUserEvents
CometChatUserEvents.addUserListener("unique-tag", new CometChatUserEvents() {
@Override
public void ccUserBlocked(User user) { }
@Override
public void ccUserUnblocked(User user) { }
});
CometChatGroupEvents
CometChatGroupEvents.addGroupListener("unique-tag", new CometChatGroupEvents() {
@Override
public void ccGroupCreated(Group group) { }
@Override
public void ccGroupDeleted(Group group) { }
@Override
public void ccGroupMemberJoined(User joinedUser, Group joinedGroup) { }
@Override
public void ccGroupMemberKicked(Action action, User kicked, User kickedBy, Group from) { }
@Override
public void ccGroupMemberBanned(Action action, User banned, User bannedBy, Group from) { }
});
CometChatCallEvents
CometChatCallEvents.addListener("unique-tag", new CometChatCallEvents() {
@Override
public void ccOutgoingCall(Call call) { }
@Override
public void ccCallAccepted(Call call) { }
@Override
public void ccCallRejected(Call call) { }
@Override
public void ccCallEnded(Call call) { }
});
5. Custom view slots on components
Most components support custom view injection via Function3<Context, User, Group, View>:
CometChatMessageHeader header = findViewById(R.id.header);
header.setSubtitleView((context, user, group) -> {
TextView subtitle = new TextView(context);
if (user != null) {
subtitle.setText(user.getStatus().equals("online") ? "Active now" : "Offline");
}
return subtitle;
});
Hard rules
- Always extend
DataSourceDecorator, never implementDataSourcedirectly. The decorator preserves existing behavior. - Register
ChatConfigurator.enable()AFTERCometChatUIKit.init()succeeds. The configurator resets on init. - Always remove event listeners when the Activity/Fragment is destroyed. Use
onDestroy()oronDestroyView(). - Template view slots use
MessagesViewHolderListener. Implement bothcreateView()andbindView().
Capabilities
Install
Quality
deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 27 github stars · SKILL.md body (9,836 chars)