Skip to main content
{
  "component": "CometChatMessageList",
  "package": "com.cometchat.chatuikit.messagelist",
  "xmlElement": "<com.cometchat.chatuikit.messagelist.CometChatMessageList />",
  "description": "Scrollable list of messages for a conversation with real-time updates, reactions, threaded replies, and message actions.",
  "primaryOutput": {
    "method": "setOnThreadRepliesClick",
    "type": "ThreadReplyClick"
  },
  "methods": {
    "data": {
      "setUser": {
        "type": "User",
        "note": "Sets the user for a one-on-one conversation"
      },
      "setGroup": {
        "type": "Group",
        "note": "Sets the group for a group conversation"
      },
      "setMessagesRequestBuilder": {
        "type": "MessagesRequest.MessagesRequestBuilder",
        "default": "SDK default",
        "note": "Pass the builder, not the result of .build()"
      },
      "setReactionsRequestBuilder": {
        "type": "ReactionsRequest.ReactionsRequestBuilder",
        "default": "SDK default",
        "note": "Custom builder for fetching reactions"
      }
    },
    "callbacks": {
      "setOnThreadRepliesClick": "ThreadReplyClick",
      "setOnReactionClick": "OnReactionClick",
      "setOnReactionLongClick": "OnReactionLongClick",
      "setOnAddMoreReactionsClick": "OnAddMoreReactionsClick",
      "setOnReactionListItemClick": "OnReactionListItemClick",
      "setOnError": "OnError",
      "setOnLoad": "OnLoad<BaseMessage>",
      "setOnEmpty": "OnEmpty"
    },
    "visibility": {
      "setErrorStateVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" },
      "setAvatarVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setReceiptsVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setStickyDateVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setReplyInThreadOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setTranslateMessageOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setEditMessageOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setDeleteMessageOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setMessageReactionOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setMessagePrivatelyOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setCopyMessageOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setMessageInfoOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setGroupActionMessageVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setReplyOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setShareMessageOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setMarkAsUnreadOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setFlagOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
      "setModerationViewVisibility": { "type": "int", "default": "View.VISIBLE" }
    },
    "viewSlots": {
      "setHeaderView": "View — custom view above the message list",
      "setFooterView": "View — custom view below the message list",
      "setLoadingStateView": "@LayoutRes int — loading spinner",
      "setEmptyStateView": "@LayoutRes int — empty state",
      "setErrorStateView": "@LayoutRes int — error state",
      "setNewMessageIndicatorView": "View — new message indicator",
      "setAIAssistantEmptyChatGreetingView": "@LayoutRes int — AI assistant greeting",
      "setTemplates": "List<CometChatMessageTemplate> — message bubble templates",
      "setTextFormatters": "List<CometChatTextFormatter> — text formatters (mentions, etc.)"
    },
    "advanced": {
      "scrollToBottom": "void — scrolls to the bottom of the list",
      "scrollToMessageId": "long — scrolls to a specific message",
      "gotoMessage": "long — navigates to a specific message by ID",
      "generateConversationSummary": "void — triggers AI conversation summary",
      "getAdapter": "MessageAdapter — internal adapter access",
      "setAdapter": "MessageAdapter — replace the default adapter",
      "getViewModel": "MessageListViewModel — internal ViewModel access",
      "getRecyclerView": "RecyclerView — internal RecyclerView access",
      "setParentMessage": "long — sets parent message ID for threaded view",
      "setAutoFetch": "boolean — controls automatic message fetching",
      "addMessage": "BaseMessage — programmatically adds a message",
      "setList": "List<BaseMessage> — replaces the entire message list",
      "updateMessage": "int — updates a message at a given index",
      "copyMessage": "BaseMessage — copies message text to clipboard",
      "shareMessage": "void — shares the selected message",
      "showMessageInformation": "void — shows message info bottom sheet"
    },
    "style": {
      "setStyle": {
        "type": "@StyleRes int",
        "parent": "CometChatMessageListStyle"
      }
    }
  },
  "events": [],
  "sdkListeners": []
}

Where It Fits

CometChatMessageList is a message display component. It requires either a User or Group object to fetch and render messages. Wire it with CometChatMessageHeader and CometChatMessageComposer to build a complete messaging layout.
ChatActivity.kt
class ChatActivity : AppCompatActivity() {

    private lateinit var messageHeader: CometChatMessageHeader
    private lateinit var messageList: CometChatMessageList
    private lateinit var messageComposer: CometChatMessageComposer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_chat)

        messageHeader = findViewById(R.id.message_header)
        messageList = findViewById(R.id.message_list)
        messageComposer = findViewById(R.id.message_composer)

        // Set the user for all components
        messageHeader.setUser(user)
        messageList.setUser(user)
        messageComposer.setUser(user)
    }
}

Quick Start

Add the component to your layout XML:
layout_activity.xml
<com.cometchat.chatuikit.messagelist.CometChatMessageList
                android:id="@+id/message_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:background="@android:color/transparent" />
Prerequisites: CometChat SDK initialized with CometChatUIKit.init(), a user logged in, and the cometchat-chat-uikit-android dependency added. Set a User or Group object in your Activity:
YourActivity.kt
val cometChatMessageList = findViewById<CometChatMessageList>(R.id.message_list)
cometChatMessageList.setUser(user)
For a group conversation, call .setGroup(group) with a Group object instead of .setUser(user).
Simply adding the MessageList component to the layout will only display the loading indicator. To fetch messages for a specific entity, you need to supplement it with User or Group Object.

Filtering Messages

Pass a MessagesRequest.MessagesRequestBuilder to setMessagesRequestBuilder. Pass the builder instance — not the result of .build().
val messagesRequest = MessagesRequest.MessagesRequestBuilder()
    .setSearchKeyword("your search keyword")
    .setUID("user uid")

messageList.messagesRequestBuilder = messagesRequest

Filter Recipes

RecipeCode
Search by keywordbuilder.setSearchKeyword("hello")
Filter by UIDbuilder.setUID("user_uid")
Filter by GUIDbuilder.setGUID("group_guid")
Limit per pagebuilder.setLimit(30)
Filter by categorybuilder.setCategory("message")
Filter by typebuilder.setType("text")
Unread onlybuilder.setUnread(true)
Hide deleted messagesbuilder.hideDeletedMessages(true)
The following parameters in MessagesRequestBuilder will always be altered inside the message list:
  1. UID
  2. GUID
  3. types
  4. categories
The component uses infinite scroll — older messages load as the user scrolls up. Refer to MessagesRequestBuilder for the full builder API.

Reactions Request Builder

Use setReactionsRequestBuilder to customize how reactions are fetched:
val reactionsBuilder = ReactionsRequest.ReactionsRequestBuilder()
messageList.setReactionsRequestBuilder(reactionsBuilder)

Actions and Events

Callback Methods

setOnThreadRepliesClick

Fires when a user taps a threaded message bubble. No predefined behavior.
YourActivity.kt
cometchatMessageList.onThreadRepliesClick =
            ThreadReplyClick { context, baseMessage, cometchatMessageTemplate -> }
What this does: Registers a callback that fires when a user taps a threaded message bubble. The callback receives the context, the baseMessage, and the cometchatMessageTemplate.

setOnError

Fires on internal errors (network failure, auth issue, SDK exception).
YourActivity.kt
cometchatMessageList.setOnError(object : OnError {
    override fun onError(e: CometChatException) {
        // Your Exception Handling code.
    }
})
What this does: Registers an error listener. If the component encounters an error (e.g., network failure), your callback receives the CometChatException.

setOnLoad

Fires when the list is successfully fetched and loaded.
YourActivity.kt
cometchatMessageList.setOnLoad(object : OnLoad<BaseMessage?> {
    override fun onLoad(list: MutableList<BaseMessage?>?) {

    }
})
What this does: Registers a callback that fires after the message list is fetched and rendered. The callback receives the list of loaded BaseMessage objects.

setOnEmpty

Fires when the list is empty, enabling custom handling such as showing a placeholder.
YourActivity.kt
cometchatMessageList.setOnEmpty{
            
    }
What this does: Registers a callback that fires when the message list has no items. Use this to show a custom empty-state message or trigger other logic.

setOnReactionClick

Fires when a reaction is tapped, enabling custom reaction interactions.
YourActivity.kt
cometchatMessageList.onReactionClick = OnReactionClick { emoji, baseMessage -> }
What this does: Replaces the default reaction-click behavior. When a user taps a reaction, your custom lambda executes with the emoji and baseMessage.

setOnReactionLongClick

Fires when a user long-presses on a reaction pill.
YourActivity.kt
cometchatMessageList.onReactionLongClick = OnReactionLongClick { emoji, baseMessage -> }
What this does: Replaces the default reaction long-press behavior. When a user long-presses a reaction pill, your custom lambda executes with the emoji and baseMessage.

setOnAddMoreReactionsClick

Fires when a user clicks the “Add More Reactions” button.
YourActivity.kt
cometchatMessageList.onAddMoreReactionsClick =
        OnAddMoreReactionsClick { 
                
    }
What this does: Replaces the default “Add More Reactions” button behavior. Your callback receives the baseMessage that the user wants to react to.

setOnReactionListItemClick

Fires when a reaction list item is clicked in CometChatReactionsList.
YourActivity.kt
cometchatMessageList.onReactionListItemClick =
            OnReactionListItemClick { reaction, message -> } 
What this does: Replaces the default reaction list item click behavior. Your callback receives the reaction and message objects.
  • Verify: After setting an action callback, trigger the corresponding user interaction (thread reply tap, reaction click, reaction long-press) and confirm your custom logic executes instead of the default behavior.

Global UI Events

The MessageList component does not emit any global UI events of its own.

SDK Events (Real-Time, Automatic)

The component listens to SDK message events internally. No manual attachment needed unless additional side effects are required.
Automatic: new messages, edits, deletions, and reactions update the list in real time.

Functionality

Small functional customizations such as toggling visibility of UI elements, setting custom sounds, configuring alignment, and enabling AI features.
val cometChatMessageList = findViewById<CometChatMessageList>(R.id.message_list)
cometChatMessageList.setUser(user)
cometChatMessageList.setErrorStateVisibility(View.GONE)
cometChatMessageList.setReceiptsVisibility(View.GONE)
MethodDescriptionCode
setUserSets the user object to fetch messages for a one-on-one conversation.setUser(user);
setGroupSets the group object to fetch messages for a group conversation.setGroup(group);
setMessageAlignmentSets the alignment of messages (leftAligned or standard).setMessageAlignment(UIKitConstants.MessageListAlignment.STANDARD);
setErrorStateVisibilityToggles visibility of the error state.setErrorStateVisibility(View.GONE);
disableSoundForMessagesEnables/disables sound for incoming/outgoing messages, default false.disableSoundForMessages(false);
setCustomSoundForMessagesSets a custom sound for outgoing messages.setCustomSoundForMessages(@RawRes resource);
setAvatarVisibilityToggles visibility for avatar.setAvatarVisibility(View.GONE);
scrollToBottomOnNewMessageIf true, scrolls to bottom on new message. Default is false.scrollToBottomOnNewMessage(true);
setReceiptsVisibilityControls visibility of read receipts without disabling marking messages as read/delivered.setReceiptsVisibility(View.GONE);
setQuickReactionsReplaces the predefined set of quick reactions.setQuickReactions(Arrays.asList("👻","😈","🙀","🤡","❤️"));
setStickyDateVisibilityToggles visibility for sticky date header.setStickyDateVisibility(View.GONE);
setReplyInThreadOptionVisibilityToggles visibility for thread reply option.setReplyInThreadOptionVisibility(View.GONE);
setTranslateMessageOptionVisibilityToggles visibility for translate option.setTranslateMessageOptionVisibility(View.GONE);
setEditMessageOptionVisibilityToggles visibility for edit option.setEditMessageOptionVisibility(View.GONE);
setDeleteMessageOptionVisibilityToggles visibility for delete option.setDeleteMessageOptionVisibility(View.GONE);
setMessageReactionOptionVisibilityToggles visibility for reaction option.setMessageReactionOptionVisibility(View.GONE);
setMessagePrivatelyOptionVisibilityToggles visibility for private message option.setMessagePrivatelyOptionVisibility(View.GONE);
setCopyMessageOptionVisibilityToggles visibility for copy option.setCopyMessageOptionVisibility(View.GONE);
setMessageInfoOptionVisibilityToggles visibility for info option.setMessageInfoOptionVisibility(View.GONE);
setGroupActionMessageVisibilityToggles visibility for group action messages.setGroupActionMessageVisibility(View.GONE);
setReplyOptionVisibilityToggles visibility for the reply option in the action sheet.setReplyOptionVisibility(View.GONE);
setShareMessageOptionVisibilityToggles visibility for the share message option.setShareMessageOptionVisibility(View.GONE);
setMarkAsUnreadOptionVisibilityToggles visibility for the mark-as-unread option.setMarkAsUnreadOptionVisibility(View.GONE);
setFlagOptionVisibilityToggles visibility for the flag/report option.setFlagOptionVisibility(View.GONE);
setModerationViewVisibilityToggles visibility for the moderation view.setModerationViewVisibility(View.GONE);
setSwipeToReplyEnabledEnables or disables swipe-to-reply gesture. Default is true.setSwipeToReplyEnabled(false);
setStartFromUnreadMessagesWhen true, scrolls to the first unread message on load.setStartFromUnreadMessages(true);
setEnableConversationSummaryControls whether AI conversation summary is generated for conversations with many unread messages.setEnableConversationSummary(true);
setEnableConversationStarterControls whether conversation starters are generated in new conversations.setEnableConversationStarter(true);
setEnableSmartRepliesEnables smart replies for quick responses.setEnableSmartReplies(true);
setAISmartRepliesKeywordsDefines keywords in incoming messages that trigger Smart Replies.setAISmartRepliesKeywords(Arrays.asList("hello", "hi"));
setSmartRepliesDelayDurationSets the delay before Smart Replies are fetched after a message is received.setSmartRepliesDelayDuration(5000);
setUnreadMessageThresholdSets the threshold for unread messages before triggering conversation summary.setUnreadMessageThreshold(10);
setFlagRemarkInputFieldVisibilityToggles visibility for the remark input field in the flag/report dialog.setFlagRemarkInputFieldVisibility(View.GONE);
setFlagReasonLocalizationSets localization map for flag/report reason labels.setFlagReasonLocalization(map);
setStreamingSpeedSets the streaming speed for AI-generated content.setStreamingSpeed(100);
refreshStyleRefreshes the style of the message list.refreshStyle();
  • Verify: After calling a visibility method, confirm the corresponding UI element is shown or hidden. After calling disableSoundForMessages(true), confirm no sound plays on incoming messages.

Custom View Slots

Each slot replaces a section of the default UI.
SlotMethodReplaces
Header viewsetHeaderView(View)Custom view above the message list
Footer viewsetFooterView(View)Custom view below the message list
Loading viewsetLoadingStateView(@LayoutRes int)Loading spinner
Empty viewsetEmptyStateView(@LayoutRes int)Empty state
Error viewsetErrorStateView(@LayoutRes int)Error state
New message indicatorsetNewMessageIndicatorView(View)New message indicator
AI greeting viewsetAIAssistantEmptyChatGreetingView(@LayoutRes int)AI assistant empty chat greeting
Message templatessetTemplates(List<CometChatMessageTemplate>)Message bubble templates
Text formatterssetTextFormatters(List<CometChatTextFormatter>)Text formatters (mentions, etc.)

setHeaderView

Sets a custom header view displayed at the top of the message list.
Create a custom_header_layout.xml layout:
custom_header_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#EDEAFA"
    android:orientation="horizontal">

    <com.google.android.material.card.MaterialCardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/cometchat_margin_4"
        android:layout_marginTop="@dimen/cometchat_margin_1"
        android:layout_marginBottom="@dimen/cometchat_margin_1"
        android:elevation="0dp"
        app:cardCornerRadius="@dimen/cometchat_radius_max"
        app:cardElevation="0dp"
        app:strokeColor="?attr/cometchatStrokeColorLight"
        app:strokeWidth="1dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cometchat_padding_3"
            android:layout_marginTop="@dimen/cometchat_padding_1"
            android:layout_marginEnd="@dimen/cometchat_padding_3"
            android:layout_marginBottom="@dimen/cometchat_padding_1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="20dp"
                android:layout_height="@dimen/cometchat_20dp"
                android:src="@drawable/cometchat_ic_file_upload"
                app:tint="?attr/cometchatPrimaryColor" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/cometchat_margin_1"
                android:text="Notes"
                android:textAppearance="?attr/cometchatTextAppearanceCaption1Regular"
                android:textColor="?attr/cometchatPrimaryColor" />
        </LinearLayout>
    </com.google.android.material.card.MaterialCardView>

    <com.google.android.material.card.MaterialCardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/cometchat_margin_4"
        android:layout_marginTop="@dimen/cometchat_margin_1"
        android:layout_marginBottom="@dimen/cometchat_margin_1"
        android:elevation="0dp"
        app:cardCornerRadius="@dimen/cometchat_radius_max"
        app:cardElevation="0dp"
        app:strokeColor="?attr/cometchatStrokeColorLight"
        app:strokeWidth="1dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cometchat_padding_3"
            android:layout_marginTop="@dimen/cometchat_padding_1"
            android:layout_marginEnd="@dimen/cometchat_padding_3"
            android:layout_marginBottom="@dimen/cometchat_padding_1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="20dp"
                android:layout_height="@dimen/cometchat_20dp"
                android:src="@drawable/src_icons_pin"
                app:tint="?attr/cometchatPrimaryColor" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/cometchat_margin_1"
                android:text="Pinned Messages"
                android:textAppearance="?attr/cometchatTextAppearanceCaption1Regular"
                android:textColor="?attr/cometchatPrimaryColor" />
        </LinearLayout>
    </com.google.android.material.card.MaterialCardView>

    <com.google.android.material.card.MaterialCardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/cometchat_margin_4"
        android:layout_marginTop="@dimen/cometchat_margin_1"
        android:layout_marginBottom="@dimen/cometchat_margin_1"
        android:elevation="0dp"
        app:cardCornerRadius="@dimen/cometchat_radius_max"
        app:cardElevation="0dp"
        app:strokeColor="?attr/cometchatStrokeColorLight"
        app:strokeWidth="1dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cometchat_padding_3"
            android:layout_marginTop="@dimen/cometchat_padding_1"
            android:layout_marginEnd="@dimen/cometchat_padding_3"
            android:layout_marginBottom="@dimen/cometchat_padding_1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="20dp"
                android:layout_height="@dimen/cometchat_20dp"
                android:src="@drawable/cometchat_link_file_icon"
                app:tint="?attr/cometchatPrimaryColor" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/cometchat_margin_1"
                android:text="Saved Links"
                android:textAppearance="?attr/cometchatTextAppearanceCaption1Regular"
                android:textColor="?attr/cometchatPrimaryColor" />
        </LinearLayout>
    </com.google.android.material.card.MaterialCardView>

</LinearLayout>
What this does: Defines a custom header layout with three pill-shaped buttons: “Notes”, “Pinned Messages”, and “Saved Links”. Each button uses a MaterialCardView with an icon and label styled with the primary color.
cometChatMessageList.setHeaderView(View.inflate(context, R.layout.custom_header_layout, null))
What this does: Inflates the custom_header_layout.xml and sets it as the header view of the message list. The three pill buttons display above the messages.

setFooterView

Sets a custom footer view displayed at the bottom of the message list.
custom_footer_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#EDEAFA"
    android:orientation="horizontal">

    <com.google.android.material.card.MaterialCardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/cometchat_margin_4"
        android:layout_marginTop="@dimen/cometchat_margin_1"
        android:layout_marginBottom="@dimen/cometchat_margin_1"
        android:elevation="0dp"
        app:cardCornerRadius="@dimen/cometchat_radius_max"
        app:cardElevation="0dp"
        app:strokeColor="?attr/cometchatStrokeColorLight"
        app:strokeWidth="1dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cometchat_padding_3"
            android:layout_marginTop="@dimen/cometchat_padding_1"
            android:layout_marginEnd="@dimen/cometchat_padding_3"
            android:layout_marginBottom="@dimen/cometchat_padding_1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="20dp"
                android:layout_height="@dimen/cometchat_20dp"
                android:src="@drawable/cometchat_ic_file_upload"
                app:tint="?attr/cometchatPrimaryColor" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/cometchat_margin_1"
                android:text="Notes"
                android:textAppearance="?attr/cometchatTextAppearanceCaption1Regular"
                android:textColor="?attr/cometchatPrimaryColor" />
        </LinearLayout>
    </com.google.android.material.card.MaterialCardView>

    <com.google.android.material.card.MaterialCardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/cometchat_margin_4"
        android:layout_marginTop="@dimen/cometchat_margin_1"
        android:layout_marginBottom="@dimen/cometchat_margin_1"
        android:elevation="0dp"
        app:cardCornerRadius="@dimen/cometchat_radius_max"
        app:cardElevation="0dp"
        app:strokeColor="?attr/cometchatStrokeColorLight"
        app:strokeWidth="1dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cometchat_padding_3"
            android:layout_marginTop="@dimen/cometchat_padding_1"
            android:layout_marginEnd="@dimen/cometchat_padding_3"
            android:layout_marginBottom="@dimen/cometchat_padding_1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="20dp"
                android:layout_height="@dimen/cometchat_20dp"
                android:src="@drawable/src_icons_pin"
                app:tint="?attr/cometchatPrimaryColor" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/cometchat_margin_1"
                android:text="Pinned Messages"
                android:textAppearance="?attr/cometchatTextAppearanceCaption1Regular"
                android:textColor="?attr/cometchatPrimaryColor" />
        </LinearLayout>
    </com.google.android.material.card.MaterialCardView>

    <com.google.android.material.card.MaterialCardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/cometchat_margin_4"
        android:layout_marginTop="@dimen/cometchat_margin_1"
        android:layout_marginBottom="@dimen/cometchat_margin_1"
        android:elevation="0dp"
        app:cardCornerRadius="@dimen/cometchat_radius_max"
        app:cardElevation="0dp"
        app:strokeColor="?attr/cometchatStrokeColorLight"
        app:strokeWidth="1dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cometchat_padding_3"
            android:layout_marginTop="@dimen/cometchat_padding_1"
            android:layout_marginEnd="@dimen/cometchat_padding_3"
            android:layout_marginBottom="@dimen/cometchat_padding_1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="20dp"
                android:layout_height="@dimen/cometchat_20dp"
                android:src="@drawable/cometchat_link_file_icon"
                app:tint="?attr/cometchatPrimaryColor" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/cometchat_margin_1"
                android:text="Saved Links"
                android:textAppearance="?attr/cometchatTextAppearanceCaption1Regular"
                android:textColor="?attr/cometchatPrimaryColor" />
        </LinearLayout>
    </com.google.android.material.card.MaterialCardView>

</LinearLayout>
What this does: Defines a custom footer layout with three pill-shaped buttons: “Notes”, “Pinned Messages”, and “Saved Links”. Each button uses a MaterialCardView with an icon and label styled with the primary color.
cometChatMessageList.setFooterView(View.inflate(context, R.layout.custom_footer_layout, null))
What this does: Inflates the custom_footer_layout.xml and sets it as the footer view of the message list. The three pill buttons display below the messages.

setLoadingStateView

Customizes the loading indicator when messages are being fetched.
cometchatMessageList.setLoadingStateView(R.layout.your_loading_view)
What this does: Replaces the default loading spinner with your custom layout resource. The custom view displays while messages are being fetched.

setEmptyStateView

Defines a custom view displayed when no messages are available.
cometchatMessageList.setEmptyStateView(R.layout.your_empty_view)
What this does: Replaces the default empty state with your custom layout resource. The custom view displays when the message list has no items.

setErrorStateView

Custom error state view displayed when fetching messages fails.
cometchatMessageList.setErrorStateView(R.layout.your_error_view)
What this does: Replaces the default error state with your custom layout resource. The custom view displays when the component encounters an error during message fetching.

setNewMessageIndicatorView

Replaces the default “new messages” indicator that appears when new messages arrive while the user has scrolled up.
YourActivity.kt
val customIndicator = LayoutInflater.from(this).inflate(R.layout.custom_new_message_indicator, null)
cometchatMessageList.setNewMessageIndicatorView(customIndicator)
What this does: Replaces the default new message indicator with a custom layout. The indicator appears when new messages arrive while the user is scrolled up in the message list.

setTemplates

CometChatMessageTemplate is a pre-defined structure for creating message views (message bubbles). For more information, refer to CometChatMessageTemplate.

setTextFormatters

Assigns the list of text formatters. If the provided list is not null, it sets the list. Otherwise, it assigns the default text formatters retrieved from the data source. To configure the existing Mentions look and feel check out MentionsFormatter Guide.
themes.xml
<style name="CustomIncomingMessageBubbleMentionStyle" parent="CometChatIncomingBubbleMentionsStyle">
    <item name="cometchatMentionTextAppearance">?attr/cometchatTextAppearanceBodyRegular</item>
    <item name="cometchatMentionTextColor">#D6409F</item>
    <item name="cometchatMentionBackgroundColor">#D6409F</item>
    <item name="cometchatSelfMentionTextColor">#30A46C</item>
    <item name="cometchatSelfMentionTextAppearance">?attr/cometchatTextAppearanceBodyRegular</item>
    <item name="cometchatSelfMentionBackgroundColor">#30A46C</item>
</style>

<style name="CustomOutgoingMessageBubbleMentionStyle" parent="CometChatOutgoingBubbleMentionsStyle">
    <item name="cometchatMentionTextAppearance">?attr/cometchatTextAppearanceBodyRegular</item>
    <item name="cometchatMentionTextColor">#FFFFFF</item>
    <item name="cometchatMentionBackgroundColor">#F9F8FD</item>
    <item name="cometchatSelfMentionTextColor">#30A46C</item>
    <item name="cometchatSelfMentionTextAppearance">?attr/cometchatTextAppearanceBodyRegular</item>
    <item name="cometchatSelfMentionBackgroundColor">#30A46C</item>
</style>
What this does: Defines custom mention styles for incoming and outgoing message bubbles. Incoming mentions appear in pink (#D6409F) and outgoing mentions appear in white (#FFFFFF), both with green self-mentions (#30A46C).

// Initialize CometChatMentionsFormatter
val mentionFormatter = CometChatMentionsFormatter(context)

//set style to customize bubble mention text
mentionFormatter.setOutgoingBubbleMentionTextStyle(context, R.style.CustomOutgoingMessageBubbleMentionStyle)

mentionFormatter.setIncomingBubbleMentionTextStyle(context, R.style.CustomIncomingMessageBubbleMentionStyle)

// This can be passed as an array of formatter in CometChatMessageList by using setTextFormatters method.
val textFormatters: MutableList<CometChatTextFormatter> = ArrayList()
textFormatters.add(mentionFormatter)
messageList.setTextFormatters(textFormatters)
What this does: Creates a CometChatMentionsFormatter, applies custom outgoing and incoming mention styles, adds it to a list of text formatters, and passes that list to the message list component. Mentions in message bubbles render with the custom colors.

setDateFormat

Specifies a custom format for displaying sticky date separators in the chat.
messageList.setDateFormat(SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()))
What this does: Sets the sticky date separator format to “MMM dd, yyyy” (e.g., “Jul 10, 2024”) using the device’s default locale.

setTimeFormat

Defines the format in which time appears for each message bubble.
messageList.setTimeFormat(SimpleDateFormat("hh:mm a", Locale.getDefault()))
What this does: Sets the message bubble time format to “hh:mm a” (e.g., “02:30 PM”) using the device’s default locale.

setDateTimeFormatter

Provides a custom implementation of DateTimeFormatterCallback to configure how time and date values are displayed. Each method corresponds to a specific case:
  • time(long timestamp) — Custom full timestamp format
  • today(long timestamp) — Called when a message is from today
  • yesterday(long timestamp) — Called for yesterday’s messages
  • lastWeek(long timestamp) — Messages from the past week
  • otherDays(long timestamp) — Older messages
  • minutes(long diffInMinutesFromNow, long timestamp) — e.g., “5 minutes ago”
  • hours(long diffInHourFromNow, long timestamp) — e.g., “2 hours ago”
import java.text.SimpleDateFormat
import java.util.*

cometchatMessageList.setDateTimeFormatter(object : DateTimeFormatterCallback {

        private val fullTimeFormatter = SimpleDateFormat("hh:mm a", Locale.getDefault())
        private val dateFormatter = SimpleDateFormat("dd MMM yyyy", Locale.getDefault())

        override fun time(timestamp: Long): String {
            return fullTimeFormatter.format(Date(timestamp))
        }

        override fun today(timestamp: Long): String {
            return "Today"
        }

        override fun yesterday(timestamp: Long): String {
            return "Yesterday"
        }

        override fun lastWeek(timestamp: Long): String {
            return "Last Week"
        }

        override fun otherDays(timestamp: Long): String {
            return dateFormatter.format(Date(timestamp))
        }

        override fun minutes(diffInMinutesFromNow: Long, timestamp: Long): String {
            return "$diffInMinutesFromNow mins ago"
        }

        override fun hours(diffInHourFromNow: Long, timestamp: Long): String {
            return "$diffInHourFromNow hrs ago"
        }
    });
What this does: Overrides the default date/time formatting for message timestamps. Today’s messages show “Today”, yesterday’s show “Yesterday”, recent messages show “X mins ago” or “X hrs ago”, last week’s show “Last Week”, and older messages show the full date in “dd MMM yyyy” format.
  • Verify: After setting any custom view slot, confirm the custom view renders in the correct position within the message list, and the data binding populates correctly.

Common Patterns

Hide all chrome — minimal message list

cometChatMessageList.setAvatarVisibility(View.GONE)
cometChatMessageList.setReceiptsVisibility(View.GONE)
cometChatMessageList.setStickyDateVisibility(View.GONE)
cometChatMessageList.setGroupActionMessageVisibility(View.GONE)

Hide all message action options

cometChatMessageList.setReplyInThreadOptionVisibility(View.GONE)
cometChatMessageList.setEditMessageOptionVisibility(View.GONE)
cometChatMessageList.setDeleteMessageOptionVisibility(View.GONE)
cometChatMessageList.setCopyMessageOptionVisibility(View.GONE)
cometChatMessageList.setMessageReactionOptionVisibility(View.GONE)
cometChatMessageList.setTranslateMessageOptionVisibility(View.GONE)
cometChatMessageList.setMessagePrivatelyOptionVisibility(View.GONE)
cometChatMessageList.setMessageInfoOptionVisibility(View.GONE)
cometChatMessageList.setReplyOptionVisibility(View.GONE)
cometChatMessageList.setShareMessageOptionVisibility(View.GONE)
cometChatMessageList.setMarkAsUnreadOptionVisibility(View.GONE)
cometChatMessageList.setFlagOptionVisibility(View.GONE)

Enable AI features

cometChatMessageList.setEnableSmartReplies(true)
cometChatMessageList.setEnableConversationStarter(true)
cometChatMessageList.setEnableConversationSummary(true)

Custom quick reactions

cometChatMessageList.setQuickReactions(listOf("👻", "😈", "🙀", "🤡", "❤️"))

Start from unread messages

cometChatMessageList.setStartFromUnreadMessages(true)

Advanced Methods

Scroll and Navigation

scrollToBottom

Programmatically scrolls to the bottom of the message list.
cometChatMessageList.scrollToBottom()

scrollToMessageId

Scrolls to a specific message by its ID and highlights it.
cometChatMessageList.scrollToMessageId(messageId)

gotoMessage

Navigates to a specific message by ID.
cometChatMessageList.gotoMessage(messageId)

Message Manipulation

addMessage

Programmatically adds a message to the list.
cometChatMessageList.addMessage(baseMessage)

setList

Replaces the entire message list with a new list.
cometChatMessageList.setList(messageList)

updateMessage

Updates a message at a given index.
cometChatMessageList.updateMessage(index)

Threaded Messages

setParentMessage

Sets the parent message ID for threaded message view.
cometChatMessageList.setParentMessage(parentMessageId)

AI Features

generateConversationSummary

Triggers the generation of a conversation summary by fetching it from the ViewModel.
cometChatMessageList.generateConversationSummary()

setAIAssistantSuggestedMessages

Sets suggested messages for the AI assistant.
cometChatMessageList.setAIAssistantSuggestedMessages(listOf("How can I help?", "Tell me more"))

setAiAssistantTools

Registers custom AI assistant tool call listeners.
val tools = HashMap<String, ToolCallListener>()
cometChatMessageList.setAiAssistantTools(tools)

Bubble Margins

MethodDescription
setLeftBubbleMargin(top, bottom, left, right)Sets margins for incoming (left) message bubbles
setRightBubbleMargin(top, bottom, left, right)Sets margins for outgoing (right) message bubbles
setBubbleMargin(top, bottom, left, right)Sets margins for all message bubbles

Internal Access

These methods provide direct access to internal components for advanced use cases.
MethodReturnsDescription
getAdapter()MessageAdapterThe adapter powering the RecyclerView
setAdapter(MessageAdapter)voidReplaces the default adapter with a custom one
getViewModel()MessageListViewModelThe ViewModel managing message data and state
getRecyclerView()RecyclerViewThe internal RecyclerView
getView()LinearLayoutThe root view of the component
getNewMessageLayout()MaterialCardViewThe new message indicator layout
getNewMessageImageView()ImageViewThe new message indicator image
getStickyHeaderDecoration()StickyHeaderDecorationThe sticky date header decoration
getParentMessageId()longThe parent message ID for threaded view
getMentionsFormatter()CometChatMentionsFormatterThe mentions formatter instance
atBottom()booleanWhether the list is scrolled to the bottom
isHasMore()booleanWhether more messages are available to load
setAutoFetch(boolean)voidControls automatic message fetching
setMentionAllLabelId(String, String)voidSets the mention-all label ID and display text
Use these only when the standard API is insufficient. Directly manipulating the adapter or ViewModel may conflict with the component’s internal state management.

Style

The component uses XML theme styles. Define a custom style with parent CometChatMessageListStyle in themes.xml, then apply with setStyle().
themes.xml
    <style name="CustomOutgoingMessageBubbleStyle" parent="CometChatOutgoingMessageBubbleStyle">
        <item name="cometchatMessageBubbleBackgroundColor">#F76808</item>
    </style>

    <style name="CustomCometChatMessageListStyle" parent="CometChatMessageListStyle">
        <item name="cometchatMessageListBackgroundColor">#FEEDE1</item>
        <item name="cometchatMessageListOutgoingMessageBubbleStyle">@style/CustomOutgoingMessageBubbleStyle</item>
    </style>
What this does: Defines two custom styles: CustomOutgoingMessageBubbleStyle sets the outgoing message bubble background to orange (#F76808); CustomCometChatMessageListStyle sets the message list background to light peach (#FEEDE1) and applies the custom outgoing bubble style.
cometChatMessageList.setStyle(R.style.CustomCometChatMessageListStyle)
To know more such attributes, visit the attributes file.

Programmatic Style Properties

In addition to XML theme styles, the component exposes programmatic setters for fine-grained control:
MethodTypeDescription
setIncomingMessageBubbleStyle@StyleRes intStyle for incoming message bubbles
setOutgoingMessageBubbleStyle@StyleRes intStyle for outgoing message bubbles
setDateSeparatorStyle@StyleRes intStyle for date separator headers
setDeleteDialogStyle@StyleRes intStyle for the delete confirmation dialog
setMessageInformationStyle@StyleRes intStyle for the message information sheet
setMessageOptionSheetStyle@StyleRes intStyle for the message option action sheet
setReactionListStyle@StyleRes intStyle for the reaction list bottom sheet
setModerationViewStyle@StyleRes intStyle for the moderation view
setFlagMessageStyle@StyleRes intStyle for the flag/report message dialog
setBadgeStyle@StyleRes intStyle for the unread message badge
setAISmartRepliesStyle@StyleRes intStyle for AI smart replies
setAIConversationStarterStyle@StyleRes intStyle for AI conversation starters
setAIConversationSummaryStyle@StyleRes intStyle for AI conversation summary
setErrorStateTitleTextColor@ColorInt intTitle text color for the error state
setErrorStateTitleTextAppearance@StyleRes intTitle text appearance for the error state
setErrorStateSubtitleTextColor@ColorInt intSubtitle text color for the error state
setErrorStateSubtitleTextAppearance@StyleRes intSubtitle text appearance for the error state
setNewMessageIndicatorIconTint@ColorInt intTint color for the new message indicator icon
setAddReactionIconintCustom icon for the add reaction button

Customization Matrix

What to changeWhereProperty/APIExample
Override behavior on user interactionActivity/FragmentsetOn<Event> callbackssetOnThreadRepliesClick((ctx, msg, tpl) -> { ... })
Filter which messages appearActivity/FragmentsetMessagesRequestBuildersetMessagesRequestBuilder(builder)
Customize reactions fetchingActivity/FragmentsetReactionsRequestBuildersetReactionsRequestBuilder(builder)
Toggle visibility of UI elementsActivity/Fragmentset<Feature>Visibility(int)setReceiptsVisibility(View.GONE)
Replace header/footer viewsActivity/FragmentsetHeaderView / setFooterViewsetHeaderView(view)
Change colors, fonts, spacingthemes.xmlCometChatMessageListStyle<item name="cometchatMessageListBackgroundColor">#FEEDE1</item>
Outgoing bubble stylethemes.xmlcometchatMessageListOutgoingMessageBubbleStyle<item name="cometchatMessageBubbleBackgroundColor">#F76808</item>
Apply a custom styleActivity/FragmentsetStyle(int styleRes)cometChatMessageList.setStyle(R.style.CustomCometChatMessageListStyle);
Set user for messagesActivity/FragmentsetUser(User).setUser(user);
Set group for messagesActivity/FragmentsetGroup(Group).setGroup(group);
Message alignmentActivity/FragmentsetMessageAlignment(UIKitConstants.MessageListAlignment).setMessageAlignment(UIKitConstants.MessageListAlignment.STANDARD);
Error state visibilityActivity/FragmentsetErrorStateVisibility(int).setErrorStateVisibility(View.GONE);
Incoming/outgoing message soundActivity/FragmentdisableSoundForMessages(boolean).disableSoundForMessages(true);
Custom message soundActivity/FragmentsetCustomSoundForMessages(int).setCustomSoundForMessages(@RawRes resource);
Avatar visibilityActivity/FragmentsetAvatarVisibility(int).setAvatarVisibility(View.GONE);
Scroll to bottom on new messageActivity/FragmentscrollToBottomOnNewMessage(boolean).scrollToBottomOnNewMessage(true);
Read/delivered receipts visibilityActivity/FragmentsetReceiptsVisibility(int).setReceiptsVisibility(View.GONE);
Quick reactions listActivity/FragmentsetQuickReactions(List).setQuickReactions(Arrays.asList("👻","😈","🙀","🤡","❤️"));
Sticky date visibilityActivity/FragmentsetStickyDateVisibility(int).setStickyDateVisibility(View.GONE);
Thread reply option visibilityActivity/FragmentsetReplyInThreadOptionVisibility(int).setReplyInThreadOptionVisibility(View.GONE);
Translate option visibilityActivity/FragmentsetTranslateMessageOptionVisibility(int).setTranslateMessageOptionVisibility(View.GONE);
Edit option visibilityActivity/FragmentsetEditMessageOptionVisibility(int).setEditMessageOptionVisibility(View.GONE);
Delete option visibilityActivity/FragmentsetDeleteMessageOptionVisibility(int).setDeleteMessageOptionVisibility(View.GONE);
Reaction option visibilityActivity/FragmentsetMessageReactionOptionVisibility(int).setMessageReactionOptionVisibility(View.GONE);
Private message option visibilityActivity/FragmentsetMessagePrivatelyOptionVisibility(int).setMessagePrivatelyOptionVisibility(View.GONE);
Copy option visibilityActivity/FragmentsetCopyMessageOptionVisibility(int).setCopyMessageOptionVisibility(View.GONE);
Message info option visibilityActivity/FragmentsetMessageInfoOptionVisibility(int).setMessageInfoOptionVisibility(View.GONE);
Group action message visibilityActivity/FragmentsetGroupActionMessageVisibility(int).setGroupActionMessageVisibility(View.GONE);
Reply option visibilityActivity/FragmentsetReplyOptionVisibility(int).setReplyOptionVisibility(View.GONE);
Share option visibilityActivity/FragmentsetShareMessageOptionVisibility(int).setShareMessageOptionVisibility(View.GONE);
Mark as unread optionActivity/FragmentsetMarkAsUnreadOptionVisibility(int).setMarkAsUnreadOptionVisibility(View.GONE);
Flag/report optionActivity/FragmentsetFlagOptionVisibility(int).setFlagOptionVisibility(View.GONE);
Moderation view visibilityActivity/FragmentsetModerationViewVisibility(int).setModerationViewVisibility(View.GONE);
Swipe to replyActivity/FragmentsetSwipeToReplyEnabled(boolean).setSwipeToReplyEnabled(false);
Start from unread messagesActivity/FragmentsetStartFromUnreadMessages(boolean).setStartFromUnreadMessages(true);
Conversation startersActivity/FragmentsetEnableConversationStarter(boolean).setEnableConversationStarter(true);
Smart repliesActivity/FragmentsetEnableSmartReplies(boolean).setEnableSmartReplies(true);
Smart replies keywordsActivity/FragmentsetAISmartRepliesKeywords(List).setAISmartRepliesKeywords(Arrays.asList("hello", "hi"));
Smart replies delayActivity/FragmentsetSmartRepliesDelayDuration(int).setSmartRepliesDelayDuration(5000);
Conversation summaryActivity/FragmentsetEnableConversationSummary(boolean).setEnableConversationSummary(true);
Unread message thresholdActivity/FragmentsetUnreadMessageThreshold(int).setUnreadMessageThreshold(10);
Date/time formattingActivity/FragmentsetDateTimeFormatter(DateTimeFormatterCallback)See setDateTimeFormatter code above
Sticky date formatActivity/FragmentsetDateFormat(SimpleDateFormat)messageList.setDateFormat(new SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()));
Message bubble time formatActivity/FragmentsetTimeFormat(SimpleDateFormat)messageList.setTimeFormat(new SimpleDateFormat("hh:mm a", Locale.getDefault()));
Loading viewActivity/FragmentsetLoadingStateView(int)cometchatMessageList.setLoadingStateView(R.layout.your_loading_view);
Empty viewActivity/FragmentsetEmptyStateView(int)cometchatMessageList.setEmptyStateView(R.layout.your_empty_view);
Error viewActivity/FragmentsetErrorStateView(int)cometchatMessageList.setErrorStateView(R.layout.your_error_view);
Header viewActivity/FragmentsetHeaderView(View)cometChatMessageList.setHeaderView(view);
Footer viewActivity/FragmentsetFooterView(View)cometChatMessageList.setFooterView(view);
New message indicator viewActivity/FragmentsetNewMessageIndicatorView(View)cometchatMessageList.setNewMessageIndicatorView(view);
Text formatters (mentions)Activity/FragmentsetTextFormatters(List<CometChatTextFormatter>)See setTextFormatters code above
Message templatesActivity/FragmentsetTemplates(List<CometChatMessageTemplate>)See CometChatMessageTemplate
Refresh styleActivity/FragmentrefreshStyle().refreshStyle();
Streaming speedActivity/FragmentsetStreamingSpeed(Integer).setStreamingSpeed(100);
Bubble marginsActivity/FragmentsetLeftBubbleMargin / setRightBubbleMargin / setBubbleMargin.setBubbleMargin(4, 4, 8, 8);
Internal adapter accessActivity/FragmentgetAdapter() / setAdapter()Advanced use only

Accessibility

The component renders a scrollable RecyclerView of message bubbles. Each message bubble responds to tap and long-press gestures. Avatar images include the user name as content description. Date separators and sticky headers provide temporal navigation context for screen readers. For custom views provided via setHeaderView, setFooterView, or setNewMessageIndicatorView, ensure you set android:contentDescription on visual-only elements so TalkBack can announce them. The default views handle this automatically. Read receipt indicators and reaction pills are visual-only by default. If screen reader descriptions are needed, provide them via custom views with appropriate contentDescription attributes.

Next Steps