> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-agent-in-group-react-v6.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Conversations

> Display CometChat Android UI Kit conversations with last messages, unread counts, typing indicators, presence, filters, and item callbacks.

<Accordion title="AI Integration Quick Reference">
  ```json theme={null}
  {
    "component": "CometChatConversations",
    "package": "com.cometchat.chatuikit.conversations",
    "xmlElement": "<com.cometchat.chatuikit.conversations.CometChatConversations />",
    "description": "Scrollable list of recent one-on-one and group conversations for the logged-in user.",
    "primaryOutput": {
      "method": "setOnItemClick",
      "type": "OnItemClick<Conversation>"
    },
    "methods": {
      "data": {
        "setConversationsRequestBuilder": {
          "type": "ConversationsRequest.ConversationsRequestBuilder",
          "default": "SDK default (30 per page)",
          "note": "Pass the builder, not the result of .build()"
        },
        "setDateTimeFormatter": {
          "type": "DateTimeFormatterCallback",
          "default": "Component default (hh:mm a today, Yesterday, dd MMM yyyy)"
        },
        "setDateFormat": {
          "type": "SimpleDateFormat",
          "default": "Component default"
        }
      },
      "callbacks": {
        "setOnItemClick": "OnItemClick<Conversation>",
        "setOnItemLongClick": "OnItemLongClick<Conversation>",
        "setOnBackPressListener": "OnBackPress",
        "setOnSelect": "OnSelection<Conversation>",
        "setOnError": "OnError",
        "setOnLoad": "OnLoad<Conversation>",
        "setOnEmpty": "OnEmpty",
        "setOnSearchClickListener": "OnSearchClick"
      },
      "visibility": {
        "setBackIconVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.GONE" },
        "setToolbarVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setLoadingStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setDeleteConversationOptionVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setErrorStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setEmptyStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setSeparatorVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setUserStatusVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setGroupTypeVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setReceiptsVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setSearchBoxVisibility": { "type": "int", "default": "View.VISIBLE" }
      },
      "sound": {
        "disableSoundForMessages": { "type": "boolean", "default": false },
        "setCustomSoundForMessages": { "type": "@RawRes int", "default": "built-in" }
      },
      "selection": {
        "setSelectionMode": {
          "type": "UIKitConstants.SelectionMode",
          "values": ["NONE", "SINGLE", "MULTIPLE"],
          "default": "NONE"
        }
      },
      "viewSlots": {
        "setItemView": "ConversationsViewHolderListener — entire list item row",
        "setLeadingView": "ConversationsViewHolderListener — avatar / left section",
        "setTitleView": "ConversationsViewHolderListener — name / title text",
        "setSubtitleView": "ConversationsViewHolderListener — last message preview",
        "setTrailingView": "ConversationsViewHolderListener — timestamp / badge / right section",
        "setLoadingView": "@LayoutRes int — loading spinner",
        "setEmptyView": "@LayoutRes int — empty state",
        "setErrorView": "@LayoutRes int — error state",
        "setOverflowMenu": "View — toolbar menu",
        "setOptions": "Function2<Context, Conversation, List<MenuItem>> — long-press context menu (replaces defaults)",
        "addOptions": "Function2<Context, Conversation, List<MenuItem>> — long-press context menu (appends to defaults)"
      },
      "formatting": {
        "setTextFormatters": {
          "type": "List<CometChatTextFormatter>",
          "default": "default formatters from data source"
        }
      },
      "advanced": {
        "selectConversation": "Conversation, SelectionMode — programmatic selection",
        "clearSelection": "void — clears all selected conversations",
        "getSelectedConversations": "List<Conversation> — returns selected items",
        "getRecyclerView": "RecyclerView — internal RecyclerView access",
        "getViewModel": "ConversationsViewModel — internal ViewModel access",
        "getConversationsAdapter": "ConversationsAdapter — internal adapter access",
        "setAdapter": "ConversationsAdapter — replace the default adapter",
        "getBinding": "CometchatConversationsListViewBinding — root ViewBinding",
        "hideReceipts": "boolean — hide/show read receipts at adapter level",
        "setMentionAllLabelId": "String id, String label — mention-all label"
      },
      "style": {
        "setStyle": {
          "type": "@StyleRes int",
          "parent": "CometChatConversationsStyle"
        }
      }
    },
    "events": [
      {
        "name": "CometChatConversationEvents.ccConversationDeleted",
        "payload": "Conversation",
        "description": "Conversation deleted from list"
      }
    ],
    "sdkListeners": [
      "onTextMessageReceived",
      "onMediaMessageReceived",
      "onCustomMessageReceived",
      "onTypingStarted",
      "onTypingEnded",
      "onMessagesDelivered",
      "onMessagesRead",
      "onMessagesDeliveredToAll",
      "onMessagesReadByAll",
      "onUserOnline",
      "onUserOffline",
      "onGroupMemberJoined",
      "onGroupMemberLeft",
      "onGroupMemberKicked",
      "onGroupMemberBanned",
      "onMemberAddedToGroup"
    ],
    "compositionExample": {
      "description": "Sidebar conversations wired to message view",
      "components": [
        "CometChatConversations",
        "CometChatMessageHeader",
        "CometChatMessageList",
        "CometChatMessageComposer"
      ],
      "flow": "setOnItemClick emits Conversation -> extract User/Group via getConversationWith() -> pass to MessageHeader, MessageList, MessageComposer"
    }
  }
  ```
</Accordion>

## Where It Fits

`CometChatConversations` is a list component. It renders recent conversations and emits the selected `Conversation` via `setOnItemClick`. Wire it to `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` to build a standard chat layout.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin ChatActivity.kt lines theme={null}
    class ChatActivity : AppCompatActivity() {

        private lateinit var conversations: CometChatConversations
        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)

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

            conversations.setOnItemClick { view, position, conversation ->
                if (conversation.conversationType == CometChatConstants.CONVERSATION_TYPE_USER) {
                    val user = conversation.conversationWith as User
                    messageHeader.setUser(user)
                    messageList.setUser(user)
                    messageComposer.setUser(user)
                } else {
                    val group = conversation.conversationWith as Group
                    messageHeader.setGroup(group)
                    messageList.setGroup(group)
                    messageComposer.setGroup(group)
                }
            }
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java ChatActivity.java lines theme={null}
    public class ChatActivity extends AppCompatActivity {

        private CometChatConversations conversations;
        private CometChatMessageHeader messageHeader;
        private CometChatMessageList messageList;
        private CometChatMessageComposer messageComposer;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_chat);

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

            conversations.setOnItemClick((view, position, conversation) -> {
                if (CometChatConstants.CONVERSATION_TYPE_USER.equals(conversation.getConversationType())) {
                    User user = (User) conversation.getConversationWith();
                    messageHeader.setUser(user);
                    messageList.setUser(user);
                    messageComposer.setUser(user);
                } else {
                    Group group = (Group) conversation.getConversationWith();
                    messageHeader.setGroup(group);
                    messageList.setGroup(group);
                    messageComposer.setGroup(group);
                }
            });
        }
    }
    ```
  </Tab>

  <Tab title="XML">
    ```xml activity_chat.xml lines theme={null}
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <!-- Conversation sidebar -->
        <com.cometchat.chatuikit.conversations.CometChatConversations
            android:id="@+id/conversations"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <!-- Message panel -->
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:orientation="vertical">

            <com.cometchat.chatuikit.messageheader.CometChatMessageHeader
                android:id="@+id/message_header"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <com.cometchat.chatuikit.messagelist.CometChatMessageList
                android:id="@+id/message_list"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <com.cometchat.chatuikit.messagecomposer.CometChatMessageComposer
                android:id="@+id/message_composer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

        </LinearLayout>

    </LinearLayout>
    ```
  </Tab>
</Tabs>

> On phones, you'd typically use separate Activities instead of a side-by-side layout — see the [Conversation List + Message View](/ui-kit/android/android-conversation) getting started guide.

## Quick Start

Add the component to your layout XML:

```xml layout_activity.xml lines theme={null}
<com.cometchat.chatuikit.conversations.CometChatConversations
        android:id="@+id/conversation"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/aivwqvtoO_fTqj20/images/f2c77c5b-Conversation-ac41cc6650fbb941c64f389aee910dbc.png?fit=max&auto=format&n=aivwqvtoO_fTqj20&q=85&s=9610b42b716fb244a549d2fea1fe5d04" width="1280" height="800" data-path="images/f2c77c5b-Conversation-ac41cc6650fbb941c64f389aee910dbc.png" />
</Frame>

Prerequisites: CometChat SDK initialized with `CometChatUIKit.init()`, a user logged in, and the `cometchat-chat-uikit-android` dependency added.

To add programmatically in an Activity:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(CometChatConversations(this))
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
           setContentView(new CometChatConversations(this));
        }
    ```
  </Tab>
</Tabs>

Or in a Fragment:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourFragment.kt lines theme={null}
     override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View {
        return CometChatConversations(requireContext())
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourFragment.java lines theme={null}
    @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
           return new CometChatConversations(getContext());
        }
    ```
  </Tab>
</Tabs>

## Filtering Conversations

Pass a `ConversationsRequest.ConversationsRequestBuilder` to `setConversationsRequestBuilder`. Pass the builder instance — not the result of `.build()`.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = ConversationsRequest.ConversationsRequestBuilder()
        builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER)
        builder.setLimit(50)

    cometChatConversations.setConversationsRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    ConversationsRequest.ConversationsRequestBuilder builder = new ConversationsRequest.ConversationsRequestBuilder();
                builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER);
                builder.setLimit(50);

    cometChatConversations.setConversationsRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

### Filter Recipes

| Recipe                   | Code                                                                                 |
| ------------------------ | ------------------------------------------------------------------------------------ |
| Only user conversations  | `builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER)`             |
| Only group conversations | `builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_GROUP)`            |
| Limit to 10 per page     | `builder.setLimit(10)`                                                               |
| With specific tags       | `builder.setTags(Arrays.asList("vip"))`                                              |
| Filter by user tags      | `builder.withUserAndGroupTags(true); builder.setUserTags(Arrays.asList("premium"))`  |
| Filter by group tags     | `builder.withUserAndGroupTags(true); builder.setGroupTags(Arrays.asList("support"))` |

> Default page size is 30. The component uses infinite scroll — the next page loads as the user scrolls to the bottom. Refer to [ConversationsRequestBuilder](/sdk/android/retrieve-conversations) for the full builder API.

## Actions and Events

### Callback Methods

#### `setOnItemClick`

Fires when a conversation row is tapped. Primary navigation hook — set the active conversation and render the message view.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatConversations.onItemClick = OnItemClick { view, position, conversation ->
                
        }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatConversations.setOnItemClick((view1, position, conversation) -> {
                
        });
    ```
  </Tab>
</Tabs>

> **What this does:** Replaces the default item-click behavior. When a user taps a conversation, your custom lambda executes instead of the built-in navigation.

#### `setOnItemLongClick`

Fires when a conversation row is long-pressed. Use for additional actions like delete or select.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatConversations.onItemLongClick = OnItemLongClick({ view, position, conversation ->
                
        })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatConversations.setOnItemLongClick((view1, position, conversation) -> {

        });
    ```
  </Tab>
</Tabs>

> **What this does:** Replaces the default long-press behavior. When a user long-presses a conversation, your custom lambda executes.

#### `setOnBackPressListener`

Fires when the user presses the back button in the app bar. Default: navigates to the previous activity.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatConversations.onBackPressListener = OnBackPress {

        }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatConversations.setOnBackPressListener(() -> {
                
        });
    ```
  </Tab>
</Tabs>

> **What this does:** Overrides the default back-press navigation. When the user taps the back button, your custom logic runs instead.

#### `setOnSelect`

Fires when a conversation is checked/unchecked in multi-select mode. Requires `setSelectionMode` to be set.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatConversations.setOnSelect(object : OnSelection<Conversation?> {
            override fun onSelection(t: MutableList<Conversation?>?) {
                    
            }
        })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatConversations.setOnSelect(t -> {

        });
    ```
  </Tab>
</Tabs>

> **What this does:** Registers a callback that fires when the user selects one or more conversations. The callback receives the list of selected `Conversation` objects.

#### `setOnError`

Fires on internal errors (network failure, auth issue, SDK exception).

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatConversations.setOnError {

        }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatConversations.setOnError(cometchatException -> {

        });
    ```
  </Tab>
</Tabs>

> **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.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatConversations.setOnLoad(object : OnLoad<Conversation?> {
        override fun onLoad(list: MutableList<Conversation?>?) {

        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatConversations.setOnLoad(list -> {

    });
    ```
  </Tab>
</Tabs>

> **What this does:** Registers a callback that fires after the conversation list is fetched and rendered. The callback receives the list of loaded `Conversation` objects.

#### `setOnEmpty`

Fires when the list is empty, enabling custom handling such as showing a placeholder.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatConversations.setOnEmpty{
                
        }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatConversations.setOnEmpty(() -> {
                
        });
    ```
  </Tab>
</Tabs>

> **What this does:** Registers a callback that fires when the conversation list has no items. Use this to show a custom empty-state message or trigger other logic.

#### `setOnSearchClickListener`

Fires when the user taps the search icon in the toolbar.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatConversations.setOnSearchClickListener {

        }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatConversations.setOnSearchClickListener(() -> {

        });
    ```
  </Tab>
</Tabs>

> **What this does:** Overrides the default search icon tap behavior. When the user taps the search icon, your custom logic runs instead.

* **Verify**: After setting an action callback, trigger the corresponding user interaction (tap, long-press, back, select, search) and confirm your custom logic executes instead of the default behavior.

### Global UI Events

`CometChatConversationEvents` emits events subscribable from anywhere in the application. Add a listener and remove it when no longer needed.

| Event                   | Fires when                              | Payload        |
| ----------------------- | --------------------------------------- | -------------- |
| `ccConversationDeleted` | A conversation is deleted from the list | `Conversation` |

<Tabs>
  <Tab title="Kotlin">
    ```kotlin Add Listener lines theme={null}
    CometChatConversationEvents.addListener("LISTENER_TAG", object : CometChatConversationEvents() {
        override fun ccConversationDeleted(conversation: Conversation) {
            super.ccConversationDeleted(conversation)
        }
    })
    ```

    Remove Listener

    ```
     CometChatConversationEvents.removeListener("LISTENER_TAG");
    ```
  </Tab>

  <Tab title="Java">
    ```java Add Listener lines theme={null}
    CometChatConversationEvents.addListener("YOUR_LISTENER_TAG", new CometChatConversationEvents() {
        @Override
        public void ccConversationDeleted(Conversation conversation) {
            super.ccConversationDeleted(conversation);
        }
    });
    ```

    Remove Listener

    ```
    CometChatConversationEvents.removeListener("YOUR_LISTENER_TAG");
    ```
  </Tab>
</Tabs>

### SDK Events (Real-Time, Automatic)

The component listens to these SDK events internally. No manual attachment needed unless additional side effects are required.

| SDK Listener                                                                                                         | Internal behavior                                                               |
| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `onTextMessageReceived` / `onMediaMessageReceived` / `onCustomMessageReceived`                                       | Moves conversation to top, updates last message preview and unread count        |
| `onTypingStarted` / `onTypingEnded`                                                                                  | Shows/hides typing indicator in the subtitle                                    |
| `onMessagesDelivered` / `onMessagesRead` / `onMessagesDeliveredToAll` / `onMessagesReadByAll`                        | Updates receipt ticks (unless `setReceiptsVisibility(View.GONE)`)               |
| `onUserOnline` / `onUserOffline`                                                                                     | Updates online/offline status dot (unless `setUserStatusVisibility(View.GONE)`) |
| `onGroupMemberJoined` / `onGroupMemberLeft` / `onGroupMemberKicked` / `onGroupMemberBanned` / `onMemberAddedToGroup` | Updates group conversation metadata                                             |

> Automatic: new messages, typing indicators, receipts, user presence, group membership changes.
> Manual: deleting a conversation via the SDK directly (not through the component's context menu) requires emitting `CometChatConversationEvents.ccConversationDeleted` for the UI to update.

## Functionality

Small functional customizations such as toggling visibility of UI elements, setting custom sounds, and configuring selection modes.

| Methods                                 | Description                                                                   | Code                                                                         |
| --------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `setBackIconVisibility`                 | Toggles visibility for the back button in the app bar                         | `.setBackIconVisibility(View.VISIBLE);`                                      |
| `setToolbarVisibility`                  | Toggles visibility for the toolbar in the app bar                             | `.setToolbarVisibility(View.GONE);`                                          |
| `setLoadingStateVisibility`             | Hides the loading state while fetching conversations                          | `.setLoadingStateVisibility(View.GONE);`                                     |
| `setDeleteConversationOptionVisibility` | Toggles visibility for the delete option on long press                        | `.setDeleteConversationOptionVisibility(View.GONE);`                         |
| `setErrorStateVisibility`               | Hides the error state on fetching conversations                               | `.setErrorStateVisibility(View.GONE);`                                       |
| `setEmptyStateVisibility`               | Hides the empty state on fetching conversations                               | `.setEmptyStateVisibility(View.GONE);`                                       |
| `setSeparatorVisibility`                | Controls visibility of separators in the list view                            | `.setSeparatorVisibility(View.GONE);`                                        |
| `setUserStatusVisibility`               | Controls visibility of the online status indicator                            | `.setUserStatusVisibility(View.GONE);`                                       |
| `setGroupTypeVisibility`                | Controls visibility of the group type indicator                               | `.setGroupTypeVisibility(View.GONE);`                                        |
| `setReceiptsVisibility`                 | Hides receipts shown in the subtitle without disabling read/delivered marking | `.setReceiptsVisibility(View.GONE);`                                         |
| `setSearchBoxVisibility`                | Controls visibility of the search box in the toolbar                          | `.setSearchBoxVisibility(View.GONE);`                                        |
| `setSearchInputEndIconVisibility`       | Controls visibility of the end icon in the search bar                         | `.setSearchInputEndIconVisibility(View.GONE);`                               |
| `hideReceipts`                          | Hides read receipts in the conversation list (adapter-level)                  | `.hideReceipts(true);`                                                       |
| `disableSoundForMessages`               | Disables sound notifications for incoming messages                            | `.disableSoundForMessages(true);`                                            |
| `setCustomSoundForMessages`             | Sets a custom sound file for incoming message notifications                   | `.setCustomSoundForMessages(com.cometchat.chatuikit.R.raw.cometchat_beep2);` |
| `setSelectionMode`                      | Determines the selection mode (single or multiple)                            | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);`                  |
| `setSearchInputText`                    | Sets the text in the search input field                                       | `.setSearchInputText("Sample Text");`                                        |
| `setSearchPlaceholderText`              | Sets the placeholder text for the search input field                          | `.setSearchPlaceholderText("Enter search term");`                            |

* **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. Slots that accept a `Conversation` parameter receive the conversation object for that row via the `ConversationsViewHolderListener` pattern (`createView` + `bindView`).

| Slot              | Method                                             | Replaces                                      |
| ----------------- | -------------------------------------------------- | --------------------------------------------- |
| Leading view      | `setLeadingView(ConversationsViewHolderListener)`  | Avatar / left section                         |
| Title view        | `setTitleView(ConversationsViewHolderListener)`    | Name / title text                             |
| Subtitle view     | `setSubtitleView(ConversationsViewHolderListener)` | Last message preview                          |
| Trailing view     | `setTrailingView(ConversationsViewHolderListener)` | Timestamp / badge / right section             |
| Item view         | `setItemView(ConversationsViewHolderListener)`     | Entire list item row                          |
| Loading view      | `setLoadingView(@LayoutRes int)`                   | Loading spinner                               |
| Empty view        | `setEmptyView(@LayoutRes int)`                     | Empty state                                   |
| Error view        | `setErrorView(@LayoutRes int)`                     | Error state                                   |
| Overflow menu     | `setOverflowMenu(View)`                            | Toolbar menu                                  |
| Options (replace) | `setOptions(Function2)`                            | Long-press context menu (replaces defaults)   |
| Options (append)  | `addOptions(Function2)`                            | Long-press context menu (appends to defaults) |

### `setLeadingView`

Replace the avatar / left section. Typing-aware avatar example.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
            cometchatConversations.setLeadingView(object :
                ConversationsViewHolderListener() {
                override fun createView(
                    context: Context?,
                    listItem: CometchatConversationsListItemsBinding?
                ): View? {
                    return null
                }

                override fun bindView(
                    context: Context,
                    createdView: View,
                    conversation: Conversation,
                    holder: RecyclerView.ViewHolder,
                    conversationList: List<Conversation>,
                    position: Int
                ) {
                }
            })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
            cometchatConversations.setLeadingView(new ConversationsViewHolderListener() {
                @Override
                public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
                    return null;
                }

                @Override
                public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List<Conversation> conversationList, int position) {

                }
            });
    ```
  </Tab>
</Tabs>

> **What this does:** Registers a `ConversationsViewHolderListener` that provides a custom view for the leading (left) area of each conversation item. `createView` inflates your layout, and `bindView` populates it with conversation data.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/gyYKxTizhi5zqoIK/images/50dd219e-conversation_leading_view-65768f699fe3f064c14b0491f7ce0f91.png?fit=max&auto=format&n=gyYKxTizhi5zqoIK&q=85&s=61e2ccbbca9ccdef3b8518a77c132aaa" width="2560" height="1600" data-path="images/50dd219e-conversation_leading_view-65768f699fe3f064c14b0491f7ce0f91.png" />
</Frame>

The following example shows a custom leading view with a chat-dots icon for typing indicators and an avatar with status indicator:

```xml drawable/chat_dots.xml lines theme={null}
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:viewportWidth="48"
    android:viewportHeight="48">
  <path
      android:pathData="M5,15.5C5,11.358 8.358,8 12.5,8H36C40.142,8 43.5,11.358 43.5,15.5V26.535C43.5,30.677 40.142,34.035 36,34.035H16.149C15.47,34.035 14.82,34.311 14.349,34.8L8.44,40.931C7.191,42.227 5,41.342 5,39.543V15.5Z"
      android:strokeLineJoin="round"
      android:strokeWidth="2.5"
      android:fillColor="#DCD7F6"
      android:strokeColor="#141414"/>
  <path
      android:pathData="M18.25,22.75C19.078,22.75 19.75,22.078 19.75,21.25C19.75,20.421 19.078,19.75 18.25,19.75C17.421,19.75 16.75,20.421 16.75,21.25C16.75,22.078 17.421,22.75 18.25,22.75ZM24.5,22.75C25.329,22.75 26,22.078 26,21.25C26,20.421 25.329,19.75 24.5,19.75C23.671,19.75 23,20.421 23,21.25C23,22.078 23.671,22.75 24.5,22.75ZM31,22.75C31.829,22.75 32.5,22.078 32.5,21.25C32.5,20.421 31.829,19.75 31,19.75C30.171,19.75 29.5,20.421 29.5,21.25C29.5,22.078 30.171,22.75 31,22.75Z"
      android:strokeWidth="0.5"
      android:fillColor="#141414"
      android:strokeColor="#141414"/>
</vector>
```

> **What this does:** Defines a vector drawable of a chat bubble with three dots, used as a typing indicator icon in the custom leading view.

Create a `leading_view.xml` custom layout:

```html lines theme={null}
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/conversation_leading_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true">

        <ImageView
            android:id="@+id/leading_iv"
            android:layout_width="@dimen/cometchat_48dp"
            android:layout_height="@dimen/cometchat_48dp"
            android:src="@drawable/chat_dots"
            android:visibility="gone"
            tools:ignore="MissingConstraints" />

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/leading_view"
            android:layout_width="@dimen/cometchat_48dp"
            android:layout_height="@dimen/cometchat_48dp"
            tools:ignore="MissingConstraints">

            <com.cometchat.chatuikit.shared.views.avatar.CometChatAvatar
                android:id="@+id/conversations_avatar"
                android:layout_width="@dimen/cometchat_48dp"
                android:layout_height="@dimen/cometchat_48dp" />

            <com.cometchat.chatuikit.shared.views.statusindicator.CometChatStatusIndicator
                android:id="@+id/status_and_type_indicator"
                android:layout_width="@dimen/cometchat_15dp"
                android:layout_height="@dimen/cometchat_15dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent" />
        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>
```

Inflate and bind with typing indicator tracking:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
            val typingIndicatorHashMap = HashMap<String, Boolean>()
            CometChat.addMessageListener(System.currentTimeMillis().toString() + "", object : MessageListener() {
                override fun onTypingStarted(typingIndicator: TypingIndicator) {
                    if (typingIndicator.receiverType == CometChatConstants.RECEIVER_TYPE_USER) {
                        if (typingIndicatorHashMap.containsKey(typingIndicator.sender.uid)) {
                            return
                        }
                        typingIndicatorHashMap[typingIndicator.sender.uid] = true
                    } else {
                        if (typingIndicatorHashMap.containsKey(typingIndicator.receiverId)) {
                            return
                        }
                        typingIndicatorHashMap[typingIndicator.receiverId] = true
                    }
                }

                override fun onTypingEnded(typingIndicator: TypingIndicator) {
                    if (typingIndicator.receiverType == CometChatConstants.RECEIVER_TYPE_USER) {
                        typingIndicatorHashMap.remove(typingIndicator.sender.uid)
                    } else {
                        typingIndicatorHashMap.remove(typingIndicator.receiverId)
                    }
                }
            })

            binding.cometchatConversations.setLeadingView(object : ConversationsViewHolderListener() {
                override fun createView(context: Context?, listItem: CometchatConversationsListItemsBinding?): View {
                    return LayoutInflater.from(context).inflate(R.layout.leading_view, null)
                }

                override fun bindView(
                    context: Context,
                    createdView: View,
                    conversation: Conversation,
                    holder: RecyclerView.ViewHolder,
                    conversationList: List<Conversation>,
                    position: Int
                ) {
                    val imageView = createdView.findViewById<ImageView>(R.id.leading_iv)
                    val constraintLayout = createdView.findViewById<ConstraintLayout>(R.id.leading_view)
                    val avatar = createdView.findViewById<CometChatAvatar>(R.id.conversations_avatar)
                    val statusIndicator = createdView.findViewById<CometChatStatusIndicator>(R.id.status_and_type_indicator)

                    avatar.setAvatar(ConversationsUtils.getConversationTitle(conversation), ConversationsUtils.getConversationAvatar(conversation))

                    if (conversation.conversationType == CometChatConstants.RECEIVER_TYPE_USER) {
                        if ((conversation.conversationWith as User).status.equals(CometChatConstants.USER_STATUS_ONLINE, ignoreCase = true)) {
                            if (!Utils.isBlocked((conversation.conversationWith as User))) {
                                statusIndicator.statusIndicator = StatusIndicator.ONLINE
                            } else {
                                statusIndicator.statusIndicator = StatusIndicator.OFFLINE
                            }
                        } else {
                            statusIndicator.statusIndicator = StatusIndicator.OFFLINE
                        }
                        if (typingIndicatorHashMap.containsKey((conversation.conversationWith as User).uid)) {
                            imageView.visibility = View.VISIBLE
                            constraintLayout.visibility = View.GONE
                        } else {
                            imageView.visibility = View.GONE
                            constraintLayout.visibility = View.VISIBLE
                        }
                    } else {
                        if (typingIndicatorHashMap.containsKey((conversation.conversationWith as Group).guid)) {
                            imageView.visibility = View.VISIBLE
                            constraintLayout.visibility = View.GONE
                        } else {
                            imageView.visibility = View.GONE
                            constraintLayout.visibility = View.VISIBLE
                        }
                    }
                }
            })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    HashMap<String, Boolean> typingIndicatorHashMap = new HashMap<>();
    CometChat.addMessageListener(System.currentTimeMillis() + "", new CometChat.MessageListener() {
                @Override
                public void onTypingStarted(TypingIndicator typingIndicator) {
                    if (typingIndicator.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_USER)) {
                        if (typingIndicatorHashMap.containsKey(typingIndicator.getSender().getUid())) {
                            return;
                        }
                        typingIndicatorHashMap.put(typingIndicator.getSender().getUid(), true);
                    } else {
                        if (typingIndicatorHashMap.containsKey(typingIndicator.getReceiverId())) {
                            return;
                        }
                        typingIndicatorHashMap.put(typingIndicator.getReceiverId(), true);
                    }
                }

                @Override
                public void onTypingEnded(TypingIndicator typingIndicator) {
                    if (typingIndicator.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_USER)) {
                        typingIndicatorHashMap.remove(typingIndicator.getSender().getUid());
                    } else {
                        typingIndicatorHashMap.remove(typingIndicator.getReceiverId());
                    }
                }
            });

    cometchatConversations.setLeadingView(new ConversationsViewHolderListener() {
                @Override
                public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
                    return LayoutInflater.from(context).inflate(R.layout.leading_view, null);
                }

                @Override
                public void bindView(Context context,
                                     View createdView,
                                     Conversation conversation,
                                     RecyclerView.ViewHolder holder,
                                     List<Conversation> conversationList,
                                     int position) {

                    ImageView imageView = createdView.findViewById(R.id.leading_iv);
                    ConstraintLayout constraintLayout = createdView.findViewById(R.id.leading_view);
                    CometChatAvatar avatar = createdView.findViewById(R.id.conversations_avatar);
                    CometChatStatusIndicator statusIndicator = createdView.findViewById(R.id.status_and_type_indicator);

                    avatar.setAvatar(ConversationsUtils.getConversationTitle(conversation), ConversationsUtils.getConversationAvatar(conversation));

                    if (conversation.getConversationType().equals(CometChatConstants.RECEIVER_TYPE_USER)) {
                        if (((User) conversation.getConversationWith()).getStatus().equalsIgnoreCase(CometChatConstants.USER_STATUS_ONLINE)) {
                            if (!Utils.isBlocked(((User) conversation.getConversationWith()))) {
                                statusIndicator.setStatusIndicator(StatusIndicator.ONLINE);
                            } else {
                                statusIndicator.setStatusIndicator(StatusIndicator.OFFLINE);
                            }
                        } else {
                            statusIndicator.setStatusIndicator(StatusIndicator.OFFLINE);
                        }
                        if (typingIndicatorHashMap.containsKey(((User) conversation.getConversationWith()).getUid())) {
                            imageView.setVisibility(View.VISIBLE);
                            constraintLayout.setVisibility(GONE);
                        } else {
                            imageView.setVisibility(GONE);
                            constraintLayout.setVisibility(View.VISIBLE);
                        }
                    } else {
                        if (typingIndicatorHashMap.containsKey(((Group) conversation.getConversationWith()).getGuid())) {
                            imageView.setVisibility(View.VISIBLE);
                            constraintLayout.setVisibility(GONE);
                        } else {
                            imageView.setVisibility(GONE);
                            constraintLayout.setVisibility(View.VISIBLE);
                        }
                    }
                }
            });
    ```
  </Tab>
</Tabs>

### `setTrailingView`

Replace the timestamp / badge / right section.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setTrailingView(object :
        ConversationsViewHolderListener() {
        override fun createView(
            context: Context?,
            listItem: CometchatConversationsListItemsBinding?
        ): View? {
            return null
        }

        override fun bindView(
            context: Context,
            createdView: View,
            conversation: Conversation,
            holder: RecyclerView.ViewHolder,
            conversationList: List<Conversation>,
            position: Int
        ) {
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setTrailingView(new ConversationsViewHolderListener() {
        @Override
        public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
            return null;
        }

        @Override
        public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List<Conversation> conversationList, int position) {

        }
    });
    ```
  </Tab>
</Tabs>

Relative time badge example:

Create a `custom_tail_view.xml` custom layout file:

```html lines theme={null}
<?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="wrap_content"
    android:layout_height="wrap_content">

    <com.google.android.material.card.MaterialCardView
        android:id="@+id/card"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:elevation="@dimen/cometchat_0dp"
        app:cardCornerRadius="@dimen/cometchat_6dp"
        app:cardElevation="@dimen/cometchat_0dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="@dimen/cometchat_5dp">

            <TextView
                android:id="@+id/hours"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:textAppearance="?attr/cometchatTextAppearanceHeading4Bold" />

            <TextView
                android:id="@+id/time_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?attr/cometchatTextAppearanceHeading4Bold" />

        </LinearLayout>

    </com.google.android.material.card.MaterialCardView>

</LinearLayout>
```

> **What this does:** Defines a custom trailing view layout with a `MaterialCardView` containing two `TextView` elements for displaying the time value and unit (e.g., "5" and "Min ago").

Inflate and bind with color-coded time badges:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setTrailingView(object : ConversationsViewHolderListener() {
                override fun createView(context: Context?, listItem: CometchatConversationsListItemsBinding?): View {
                    return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null)
                }

                override fun bindView(
                    context: Context,
                    createdView: View,
                    conversation: Conversation,
                    holder: RecyclerView.ViewHolder,
                    conversationList: List<Conversation>,
                    position: Int
                ) {
                    val card = createdView.findViewById<MaterialCardView>(R.id.card)
                    val tvHours = createdView.findViewById<TextView>(R.id.hours)
                    val tvMessage = createdView.findViewById<TextView>(R.id.time_title)

                    var timestamp = conversation.updatedAt * 1000

                    if (timestamp.toString().length == 10) {
                        timestamp *= 1000
                    }

                    val now = Calendar.getInstance()
                    val lastSeen = Calendar.getInstance()
                    lastSeen.timeInMillis = timestamp

                    val diffInMillis = now.timeInMillis - lastSeen.timeInMillis
                    val diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diffInMillis)
                    val diffInHours = TimeUnit.MILLISECONDS.toHours(diffInMillis)

                    if (diffInMinutes == 0L) {
                        tvHours.text = "1"
                        tvMessage.text = "Min ago"
                        card.setCardBackgroundColor(Utils.applyColorWithAlphaValue(Color.parseColor("#6852D6"), 40))
                        tvMessage.setTextColor(Color.parseColor("#6852D6"))
                        tvHours.setTextColor(Color.parseColor("#6852D6"))
                    } else if (diffInMinutes < 60) {
                        tvHours.text = diffInMinutes.toString()
                        tvMessage.text = "Min ago"
                        card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#6852D6"), 40))
                        tvMessage.setTextColor(Color.parseColor("#6852D6"))
                        tvHours.setTextColor(Color.parseColor("#6852D6"))
                    } else if (diffInHours < 10) {
                        tvHours.text = diffInHours.toString()
                        tvMessage.text = "Hr ago"
                        tvMessage.setTextColor(Color.parseColor("#FFAB00"))
                        tvHours.setTextColor(Color.parseColor("#FFAB00"))
                        card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#FFAB00"), 40))
                    } else if (diffInHours < 1000) {
                        tvHours.text = diffInHours.toString()
                        tvMessage.text = "Hr ago"
                        tvMessage.setTextColor(Color.parseColor("#F44649"))
                        tvHours.setTextColor(Color.parseColor("#F44649"))
                        card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#F44649"), 40))
                    }
                }
            })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setTrailingView(new ConversationsViewHolderListener() {
                @Override
                public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
                    return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null);
                }

                @Override
                public void bindView(Context context,
                                     View createdView,
                                     Conversation conversation,
                                     RecyclerView.ViewHolder holder,
                                     List<Conversation> conversationList,
                                     int position) {

                    MaterialCardView card = createdView.findViewById(R.id.card);
                    TextView tvHours = createdView.findViewById(R.id.hours);
                    TextView tvMessage = createdView.findViewById(R.id.time_title);

                    long timestamp = conversation.getUpdatedAt() * 1000;

                    if (String.valueOf(timestamp).length() == 10) {
                        timestamp *= 1000;
                    }

                    Calendar now = Calendar.getInstance();
                    Calendar lastSeen = Calendar.getInstance();
                    lastSeen.setTimeInMillis(timestamp);

                    long diffInMillis = now.getTimeInMillis() - lastSeen.getTimeInMillis();
                    long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diffInMillis);
                    long diffInHours = TimeUnit.MILLISECONDS.toHours(diffInMillis);

                    if (diffInMinutes == 0) {
                        tvHours.setText("1");
                        tvMessage.setText("Min ago");
                        card.setCardBackgroundColor(Utils.applyColorWithAlphaValue(Color.parseColor("#6852D6"), 40));
                        tvMessage.setTextColor(Color.parseColor("#6852D6"));
                        tvHours.setTextColor(Color.parseColor("#6852D6"));
                    } else if (diffInMinutes < 60) {
                        tvHours.setText(diffInMinutes + "");
                        tvMessage.setText("Min ago");
                        card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#6852D6"), 40));
                        tvMessage.setTextColor(Color.parseColor("#6852D6"));
                        tvHours.setTextColor(Color.parseColor("#6852D6"));
                    } else if (diffInHours < 10) {
                        tvHours.setText(diffInHours + "");
                        tvMessage.setText("Hr ago");
                        tvMessage.setTextColor(Color.parseColor("#FFAB00"));
                        tvHours.setTextColor(Color.parseColor("#FFAB00"));
                        card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#FFAB00"), 40));
                    } else if (diffInHours < 1000) {
                        tvHours.setText(diffInHours + "");
                        tvMessage.setText("Hr ago");
                        tvMessage.setTextColor(Color.parseColor("#F44649"));
                        tvHours.setTextColor(Color.parseColor("#F44649"));
                        card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#F44649"), 40));
                    }
                }
            });
    ```
  </Tab>
</Tabs>

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/8U2-5SWHI94obVDJ/images/9c92115a-conversation_trailing_view-15ca261b8d20291c19b48c7f7af81976.png?fit=max&auto=format&n=8U2-5SWHI94obVDJ&q=85&s=0036492815fa6aa10ada7da03f3eaf59" width="2560" height="1600" data-path="images/9c92115a-conversation_trailing_view-15ca261b8d20291c19b48c7f7af81976.png" />
</Frame>

### `setTitleView`

Replace the name / title text.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setTitleView(object :
        ConversationsViewHolderListener() {
        override fun createView(
            context: Context?,
            listItem: CometchatConversationsListItemsBinding?
        ): View? {
            return null
        }

        override fun bindView(
            context: Context,
            createdView: View,
            conversation: Conversation,
            holder: RecyclerView.ViewHolder,
            conversationList: List<Conversation>,
            position: Int
        ) {
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setTitleView(new ConversationsViewHolderListener() {
        @Override
        public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
            return null;
        }

        @Override
        public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List<Conversation> conversationList, int position) {

        }
    });
    ```
  </Tab>
</Tabs>

Inline user status example:

Create a `custom_title_view.xml` layout:

```xml custom_title_view.xml lines theme={null}
<?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="wrap_content"
    android:orientation="horizontal"
    android:gravity="center_vertical">

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?attr/cometchatTextAppearanceHeading4Bold"
        android:maxLines="1"
        android:ellipsize="end" />

    <TextView
        android:id="@+id/status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:textAppearance="?attr/cometchatTextAppearanceCaption1Regular"
        android:textColor="?attr/cometchatTextColorSecondary"
        android:maxLines="1"
        android:ellipsize="end"
        android:visibility="gone" />

</LinearLayout>
```

> **What this does:** Defines a custom title layout with the conversation name and an inline user status message.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setTitleView(object : ConversationsViewHolderListener() {
                override fun createView(context: Context?, listItem: CometchatConversationsListItemsBinding?): View {
                    return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null)
                }

                override fun bindView(
                    context: Context,
                    createdView: View,
                    conversation: Conversation,
                    holder: RecyclerView.ViewHolder,
                    conversationList: List<Conversation>,
                    position: Int
                ) {
                    val name = createdView.findViewById<TextView>(R.id.name)
                    val status = createdView.findViewById<TextView>(R.id.status)

                    name.text = ConversationsUtils.getConversationTitle(conversation)
                    if (conversation.conversationType == CometChatConstants.RECEIVER_TYPE_USER) {
                        status.visibility = View.VISIBLE
                        status.text = "• " + (conversation.conversationWith as User).statusMessage
                    } else {
                        status.visibility = View.GONE
                    }
                }
            })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setTitleView(new ConversationsViewHolderListener() {
                @Override
                public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
                    return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null);
                }

                @Override
                public void bindView(Context context,
                                     View createdView,
                                     Conversation conversation,
                                     RecyclerView.ViewHolder holder,
                                     List<Conversation> conversationList,
                                     int position) {

                    TextView name = createdView.findViewById(R.id.name);
                    TextView status = createdView.findViewById(R.id.status);

                    name.setText(ConversationsUtils.getConversationTitle(conversation));
                    if (conversation.getConversationType().equals(CometChatConstants.RECEIVER_TYPE_USER)) {
                        status.setVisibility(View.VISIBLE);
                        status.setText("• " + ((User) conversation.getConversationWith()).getStatusMessage());
                    } else {
                        status.setVisibility(View.GONE);
                    }
                }
            });
    ```
  </Tab>
</Tabs>

> **What this does:** Registers a `ConversationsViewHolderListener` that provides a custom title view for each conversation item. The example inflates a layout with the conversation name and an inline user status message. For group conversations, the status is hidden.

### `setSubtitleView`

Replace the last message preview text.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setSubtitleView(object :
        ConversationsViewHolderListener() {
        override fun createView(
            context: Context?,
            listItem: CometchatConversationsListItemsBinding?
        ): View? {
            return null
        }

        override fun bindView(
            context: Context,
            createdView: View,
            conversation: Conversation,
            holder: RecyclerView.ViewHolder,
            conversationList: List<Conversation>,
            position: Int
        ) {
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setSubtitleView(new ConversationsViewHolderListener() {
        @Override
        public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
            return null;
        }

        @Override
        public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List<Conversation> conversationList, int position) {

        }
    });
    ```
  </Tab>
</Tabs>

Example with last-active timestamp:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/-MogY9MW_bOB3epD/images/48bf8e47-Conversation_Subtitle_View-a52dabb66ff516b5afb85540c95ed92d.png?fit=max&auto=format&n=-MogY9MW_bOB3epD&q=85&s=6c93f80b25816ca1d829379f1e48b6b3" width="1280" height="800" data-path="images/48bf8e47-Conversation_Subtitle_View-a52dabb66ff516b5afb85540c95ed92d.png" />
</Frame>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
        cometchatConversations.setSubtitleView(object :
                ConversationsViewHolderListener() {
                override fun createView(
                    context: Context?,
                    listItem: CometchatConversationsListItemsBinding?
                ): View {
                    return TextView(context)
                }

                override fun bindView(
                    context: Context,
                    createdView: View,
                    conversation: Conversation,
                    holder: RecyclerView.ViewHolder,
                    conversationList: List<Conversation>,
                    position: Int
                ) {
                    val tvSubtitle = createdView as TextView
                    tvSubtitle.text =
                        "Last Active at: " + SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format(
                            conversation.updatedAt * 1000
                        )
                    tvSubtitle.setTextColor(Color.BLACK)
                }
            })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
        cometchatConversations.setSubtitleView(new ConversationsViewHolderListener() {
                @Override
                public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
                    return new TextView(context);
                }

                @Override
                public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List<Conversation> conversationList, int position) {
                    TextView tvSubtitle = (TextView) createdView;
                    tvSubtitle.setText("Last Active at: "+new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format(conversation.getUpdatedAt() * 1000));
                    tvSubtitle.setTextColor(Color.BLACK);
                }
            });
    ```
  </Tab>
</Tabs>

> **What this does:** Registers a `ConversationsViewHolderListener` that provides a custom subtitle view for each conversation item. The example creates a `TextView` showing the last active timestamp formatted as "dd/MM/yyyy, HH:mm:ss".

### `setItemView`

Replace the entire list item row.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setItemView(object :
        ConversationsViewHolderListener() {
        override fun createView(
            context: Context?,
            listItem: CometchatConversationsListItemsBinding?
        ): View? {
            return null
        }

        override fun bindView(
            context: Context,
            createdView: View,
            conversation: Conversation,
            holder: RecyclerView.ViewHolder,
            conversationList: List<Conversation>,
            position: Int
        ) {
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setItemView(new ConversationsViewHolderListener() {
        @Override
        public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
            return null;
        }

        @Override
        public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List<Conversation> conversationList, int position) {

        }
    });
    ```
  </Tab>
</Tabs>

Example with compact layout:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/1dpm1fhJnD7O18Uv/images/c6aa2b6b-Conversation_List_Item_View-60ff280389ca87aea84133ea03a6a620.png?fit=max&auto=format&n=1dpm1fhJnD7O18Uv&q=85&s=1683d473e620548efa6d5d4aaaf20517" width="1280" height="800" data-path="images/c6aa2b6b-Conversation_List_Item_View-60ff280389ca87aea84133ea03a6a620.png" />
</Frame>

Create an `item_converation_list.xml` custom layout file:

```html lines theme={null}
<?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:orientation="vertical">

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

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/conversation_leading_view"
            android:layout_width="@dimen/cometchat_45dp"
            android:layout_height="@dimen/cometchat_45dp">

            <com.cometchat.chatuikit.shared.views.avatar.CometChatAvatar
                android:id="@+id/custom_avatar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:cometchatAvatarPlaceHolderTextAppearance="@style/CometChatTextAppearanceHeading4.Bold"
                app:cometchatAvatarStrokeRadius="@dimen/cometchat_8dp" />

            <com.cometchat.chatuikit.shared.views.statusindicator.CometChatStatusIndicator
                android:id="@+id/status_and_type_indicator"
                android:layout_width="@dimen/cometchat_12dp"
                android:layout_height="@dimen/cometchat_12dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent" />

        </androidx.constraintlayout.widget.ConstraintLayout>

        <TextView
            android:id="@+id/tvName"
            android:layout_width="0dp"
            android:textAppearance="@style/CometChatTextAppearanceHeading4.Medium"
            android:layout_marginStart="@dimen/cometchat_margin_3"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tvDate"
            android:textAppearance="@style/CometChatTextAppearanceCaption1.Regular"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="?attr/cometchatStrokeColorLight" />

</LinearLayout>
```

> **What this does:** Defines a custom list item layout with a `CometChatAvatar`, status indicator, conversation name, and date — providing a compact, single-line conversation item design.

Inflate the XML and bind:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
            cometchatConversations.setItemView(object :
                ConversationsViewHolderListener() {
                override fun createView(
                    context: Context?,
                    listItem: CometchatConversationsListItemsBinding?
                ): View {
                    return LayoutInflater.from(context)
                        .inflate(R.layout.custom_list_item_view, null, false)
                }

                override fun bindView(
                    context: Context,
                    createdView: View,
                    conversation: Conversation,
                    holder: RecyclerView.ViewHolder,
                    conversationList: List<Conversation>,
                    position: Int
                ) {
                    val avatar = createdView.findViewById<CometChatAvatar>(R.id.custom_avatar)
                    val title = createdView.findViewById<TextView>(R.id.tvName)
                    val tvDate = createdView.findViewById<TextView>(R.id.tvDate)

                    val name = ConversationsUtils.getConversationTitle(conversation)
                    title.text = name
                    avatar.setStyle(com.cometchat.chatuikit.R.style.CometChatAvatarStyle)
                    avatar.avatarPlaceHolderTextAppearance =
                        com.cometchat.chatuikit.R.style.CometChatTextAppearanceHeading4_Bold
                    avatar.setAvatar(name, ConversationsUtils.getConversationAvatar(conversation))
                    val simpleDateFormat = SimpleDateFormat("hh:mm a")
                    val date = simpleDateFormat.format(conversation.updatedAt * 1000)
                    tvDate.text = date
                }
            })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
            cometchatConversations.setItemView(new ConversationsViewHolderListener() {
                @Override
                public View createView(Context context, CometchatConversationsListItemsBinding listItem) {
                    return LayoutInflater.from(context).inflate(R.layout.custom_list_item_view, null, false);
                }

                @Override
                public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List<Conversation> conversationList, int position) {
                    CometChatAvatar avatar = createdView.findViewById(R.id.custom_avatar);
                    TextView title = createdView.findViewById(R.id.tvName);
                    TextView tvDate = createdView.findViewById(R.id.tvDate);

                    String name = ConversationsUtils.getConversationTitle(conversation);
                    title.setText(name);
                    avatar.setStyle(com.cometchat.chatuikit.R.style.CometChatAvatarStyle);
                    avatar.setAvatarPlaceHolderTextAppearance(com.cometchat.chatuikit.R.style.CometChatTextAppearanceHeading4_Bold);
                    avatar.setAvatar(name, ConversationsUtils.getConversationAvatar(conversation));
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm a");
                    String date = simpleDateFormat.format(conversation.getUpdatedAt() * 1000);
                    tvDate.setText(date);
                }
            });
    ```
  </Tab>
</Tabs>

> **What this does:** Registers a `ConversationsViewHolderListener` that replaces the entire list item row. The example inflates a compact layout with an avatar, name, and date — replacing the default multi-line conversation item.

### `setDateTimeFormatter`

Custom date/time formatting for conversation timestamps. Implement the `DateTimeFormatterCallback` interface to control how each time range is displayed:

| Method                                               | Called when                                  |
| ---------------------------------------------------- | -------------------------------------------- |
| `time(long timestamp)`                               | Custom full timestamp format                 |
| `today(long timestamp)`                              | Message is from today                        |
| `yesterday(long timestamp)`                          | Message is from yesterday                    |
| `lastWeek(long timestamp)`                           | Message is from the past week                |
| `otherDays(long timestamp)`                          | Message is older than a week                 |
| `minute(long timestamp)`                             | Exactly 1 minute ago                         |
| `minutes(long diffInMinutesFromNow, long timestamp)` | Multiple minutes ago (e.g., "5 minutes ago") |
| `hour(long timestamp)`                               | Exactly 1 hour ago                           |
| `hours(long diffInHourFromNow, long timestamp)`      | Multiple hours ago (e.g., "2 hours ago")     |

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.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"
            }
        })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setDateTimeFormatter(new DateTimeFormatterCallback() {

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

            @Override
            public String time(long timestamp) {
                return fullTimeFormatter.format(new Date(timestamp));
            }

            @Override
            public String today(long timestamp) {
                return "Today";
            }

            @Override
            public String yesterday(long timestamp) {
                return "Yesterday";
            }

            @Override
            public String lastWeek(long timestamp) {
                return "Last Week";
            }

            @Override
            public String otherDays(long timestamp) {
                return dateFormatter.format(new Date(timestamp));
            }

            @Override
            public String minutes(long diffInMinutesFromNow, long timestamp) {
                return diffInMinutesFromNow + " mins ago";
            }

            @Override
            public String hours(long diffInHourFromNow, long timestamp) {
                return diffInHourFromNow + " hrs ago";
            }
        });
    ```
  </Tab>
</Tabs>

### `setOptions`

Replace the long-press context menu entirely.

Generic signature:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setOptions { context, conversation -> emptyList<CometChatPopupMenu.MenuItem?>() }
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setOptions((context, conversation) -> Collections.emptyList());
    ```
  </Tab>
</Tabs>

Example with a custom delete option:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/Esb0GoP81F5eUfZq/images/9415d47d-conversation_set_option-42a75eb50360de67a9bfab69beefbda3.png?fit=max&auto=format&n=Esb0GoP81F5eUfZq&q=85&s=152c9f3e81b6f16521a406a0ee63a262" width="1280" height="800" data-path="images/9415d47d-conversation_set_option-42a75eb50360de67a9bfab69beefbda3.png" />
</Frame>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setOptions { context, conversation ->
                val optionsArrayList: MutableList<CometChatPopupMenu.MenuItem> =
                    ArrayList()
                optionsArrayList.add(
                    CometChatPopupMenu.MenuItem(
                        UIKitConstants.ConversationOption.DELETE,
                        "Delete",
                        ResourcesCompat. getDrawable(resources,com.cometchat.chatuikit.R.drawable.cometchat_ic_delete, getContext()?.theme),
                        null,
                        CometChatTheme.getErrorColor(context),
                        0,
                        CometChatTheme.getErrorColor(context),
                        CometChatTheme.getTextAppearanceBodyRegular(context)
                    ) {
                        Toast.makeText(context, "Delete", Toast.LENGTH_SHORT).show()
                    }
                )
                optionsArrayList
            }
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setOptions((context, conversation) -> {
    List<CometChatPopupMenu.MenuItem> optionsArrayList = new ArrayList<>();
    optionsArrayList.add(new CometChatPopupMenu.MenuItem(UIKitConstants.ConversationOption.DELETE,
                                                                     "Delete",
                                                                     getResources().getDrawable(com.cometchat.chatuikit.R.drawable.cometchat_ic_delete),
                                                                     null,
                                                                     CometChatTheme.getErrorColor(context),
                                                                     0,
                                                                     CometChatTheme.getErrorColor(context),
                                                                     CometChatTheme.getTextAppearanceBodyRegular(context),
                                                                     () -> {
                                                                         Toast.makeText(context, "Delete", Toast.LENGTH_SHORT).show();
                                                                     }));
                return optionsArrayList;
            });
    ```
  </Tab>
</Tabs>

### `addOptions`

Append to the long-press context menu without removing defaults.

Generic signature:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.addOptions { context, conversation -> emptyList<CometChatPopupMenu.MenuItem?>() }
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.addOptions((context, conversation) -> Collections.emptyList());
    ```
  </Tab>
</Tabs>

Example with archive, pin, and mark-as-read options:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/hvldi1e9uY_02hWX/images/88283fe5-conversation_add_options-c0f407ccc43b5f040d9ab9147e17def0.png?fit=max&auto=format&n=hvldi1e9uY_02hWX&q=85&s=9b0f40492ca34b775ccda42499d64151" width="1280" height="800" data-path="images/88283fe5-conversation_add_options-c0f407ccc43b5f040d9ab9147e17def0.png" />
</Frame>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.addOptions { context, conversation ->
                val optionsArrayList: MutableList<CometChatPopupMenu.MenuItem> = ArrayList()
                optionsArrayList.add(
                    CometChatPopupMenu.MenuItem(
                        "ARCHIVE", "Archive",
                        resources.getDrawable(R.drawable.archive), null,
                        CometChatTheme.getTextColorPrimary(context), 0,
                        CometChatTheme.getTextColorPrimary(context),
                        CometChatTheme.getTextAppearanceBodyRegular(context)
                    ) { Toast.makeText(context, "Archive", Toast.LENGTH_SHORT).show() }
                )
                optionsArrayList.add(
                    CometChatPopupMenu.MenuItem(
                        "PIN", "Pin",
                        resources.getDrawable(R.drawable.pin), null,
                        CometChatTheme.getTextColorPrimary(context), 0,
                        CometChatTheme.getTextColorPrimary(context),
                        CometChatTheme.getTextAppearanceBodyRegular(context)
                    ) { Toast.makeText(context, "Pin", Toast.LENGTH_SHORT).show() }
                )
                optionsArrayList.add(
                    CometChatPopupMenu.MenuItem(
                        "MARKASREAD", "Mark as read",
                        resources.getDrawable(R.drawable.mark_as_read), null,
                        CometChatTheme.getTextColorPrimary(context), 0,
                        CometChatTheme.getTextColorPrimary(context),
                        CometChatTheme.getTextAppearanceBodyRegular(context)
                    ) { Toast.makeText(context, "Mark as read", Toast.LENGTH_SHORT).show() }
                )
                optionsArrayList
            }
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.addOptions((context, conversation) -> {
                List<CometChatPopupMenu.MenuItem> optionsArrayList = new ArrayList<>();
                optionsArrayList.add(new CometChatPopupMenu.MenuItem("ARCHIVE",
                                                                     "Archive",
                                                                     getResources().getDrawable(R.drawable.archive),
                                                                     null,
                                                                     CometChatTheme.getTextColorPrimary(context),
                                                                     0,
                                                                     CometChatTheme.getTextColorPrimary(context),
                                                                     CometChatTheme.getTextAppearanceBodyRegular(context),
                                                                     () -> Toast.makeText(context, "Archive", Toast.LENGTH_SHORT).show()));
                optionsArrayList.add(new CometChatPopupMenu.MenuItem("PIN",
                                                                     "Pin",
                                                                     getResources().getDrawable(R.drawable.pin),
                                                                     null,
                                                                     CometChatTheme.getTextColorPrimary(context),
                                                                     0,
                                                                     CometChatTheme.getTextColorPrimary(context),
                                                                     CometChatTheme.getTextAppearanceBodyRegular(context),
                                                                     () -> Toast.makeText(context, "Pin", Toast.LENGTH_SHORT).show()));
                optionsArrayList.add(new CometChatPopupMenu.MenuItem("MARKASREAD",
                                                                     "Mark as read",
                                                                     getResources().getDrawable(R.drawable.mark_as_read),
                                                                     null,
                                                                     CometChatTheme.getTextColorPrimary(context),
                                                                     0,
                                                                     CometChatTheme.getTextColorPrimary(context),
                                                                     CometChatTheme.getTextAppearanceBodyRegular(context),
                                                                     () -> Toast.makeText(context, "Mark as read", Toast.LENGTH_SHORT).show()));
                return optionsArrayList;
            });
    ```
  </Tab>
</Tabs>

### `setTextFormatters`

Custom text formatters for the conversation subtitle. See the [MentionsFormatter Guide](/ui-kit/android/mentions-formatter-guide) for details.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/gyYKxTizhi5zqoIK/images/55490fa9-mentions_conversations-1a7b847ad0af53848dc106216ac64e74.png?fit=max&auto=format&n=gyYKxTizhi5zqoIK&q=85&s=70a45e9267e09041f6af4fd7979f3e22" width="1280" height="800" data-path="images/55490fa9-mentions_conversations-1a7b847ad0af53848dc106216ac64e74.png" />
</Frame>

```xml themes.xml lines theme={null}
<style name="CustomConversationsMentionsStyle" parent="CometChatConversationsMentionsStyle">
    <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>
```

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val mentionFormatter = CometChatMentionsFormatter(context)
    mentionFormatter.setConversationsMentionTextStyle(context, R.style.CustomConversationsMentionsStyle)

    val textFormatters: MutableList<CometChatTextFormatter> = ArrayList()
    textFormatters.add(mentionFormatter)
    cometChatConversations.setTextFormatters(textFormatters)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    CometChatMentionsFormatter mentionFormatter = new CometChatMentionsFormatter(context);
    mentionFormatter.setConversationsMentionTextStyle(context, R.style.CustomConversationsMentionsStyle);

    List<CometChatTextFormatter> textFormatters = new ArrayList<>();
    textFormatters.add(mentionFormatter);
    cometChatConversations.setTextFormatters(textFormatters);
    ```
  </Tab>
</Tabs>

### `setLoadingView`

Sets a custom loading view displayed when data is being fetched.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.loadingView = R.layout.your_loading_view
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setLoadingView(R.layout.your_loading_view);
    ```
  </Tab>
</Tabs>

> **What this does:** Replaces the default loading spinner with your custom layout resource. The custom view displays while conversations are being fetched.

### `setEmptyView`

Configures a custom view displayed when there are no conversations in the list.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.emptyView = R.layout.your_empty_view
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setEmptyView(R.layout.your_empty_view);
    ```
  </Tab>
</Tabs>

> **What this does:** Replaces the default empty state with your custom layout resource. The custom view displays when the conversation list has no items.

### `setErrorView`

Defines a custom error state view that appears when an issue occurs while loading conversations.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.errorView = R.layout.your_error_view
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setErrorView(R.layout.your_error_view);
    ```
  </Tab>
</Tabs>

> **What this does:** Replaces the default error state with your custom layout resource. The custom view displays when the component encounters an error during data fetching.

### `setDateFormat`

Customizes the date format used for displaying timestamps in conversations.

Generic signature:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometChatConversations.setDateFormat(SimpleDateFormat)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometChatConversations.setDateFormat(SimpleDateFormat);
    ```
  </Tab>
</Tabs>

Example:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/RI0xrNuukR5gbXqh/images/def1212b-Conversation_Date_Pattern-62d23e137a26c9a0ee22e2c2cac64d80.png?fit=max&auto=format&n=RI0xrNuukR5gbXqh&q=85&s=c4c9b31839332e25acfddda31323d578" width="1280" height="800" data-path="images/def1212b-Conversation_Date_Pattern-62d23e137a26c9a0ee22e2c2cac64d80.png" />
</Frame>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatConversations.setDateFormat(SimpleDateFormat("dd MMM, hh:mm a",Locale.getDefault()))
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatConversations.setDateFormat(new SimpleDateFormat("dd MMM, hh:mm a",Locale.getDefault()));
    ```
  </Tab>
</Tabs>

> **What this does:** Sets the conversation date format to "dd MMM, hh:mm a" (e.g., "10 Jul, 02:30 PM") using the device's default locale.

### `setOverflowMenu`

Replace the toolbar overflow menu.

Generic signature:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometChatConversations.setOverflowMenu(view)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometChatConversations.setOverflowMenu(View v);
    ```
  </Tab>
</Tabs>

Example with a user profile popup menu:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/H3wU8vJF-bF9IftS/images/6ca194c9-Conversation_Menu-f8faec49b81b7391b9b0291c77fe34e3.png?fit=max&auto=format&n=H3wU8vJF-bF9IftS&q=85&s=1ae475aa4f90e547f4933b7f7ee15132" width="1280" height="800" data-path="images/6ca194c9-Conversation_Menu-f8faec49b81b7391b9b0291c77fe34e3.png" />
</Frame>

Create a `user_profile_popup_menu_layout.xml` custom view file:

```xml user_profile_popup_menu_layout.xml lines theme={null}
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="@dimen/cometchat_30dp"
    android:layout_height="wrap_content"
    android:layout_gravity="end"
    android:layout_marginTop="@dimen/cometchat_margin_10"
    android:background="?attr/cometchatBackgroundColor1"
    android:padding="@dimen/cometchat_padding_2"
    app:cardCornerRadius="@dimen/cometchat_radius_2"
    app:strokeColor="?attr/cometchatStrokeColorDefault"
    app:strokeWidth="@dimen/cometchat_1dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_create_conversation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawablePadding="@dimen/cometchat_padding_2"
            android:gravity="center_vertical"
            android:padding="@dimen/cometchat_padding_4"
            android:text="@string/app_create_conversation"
            android:textAppearance="?attr/textAppearanceSubtitle1"
            app:drawableStartCompat="@drawable/ic_start_conversation" />

        <View
            android:id="@+id/view_separator"
            android:layout_width="match_parent"
            android:layout_height="@dimen/cometchat_1dp"
            android:layout_gravity="center"
            android:background="?attr/cometchatStrokeColorDefault" />

        <TextView
            android:id="@+id/tv_user_name"
            style="?attr/cometchatTextAppearanceBodyRegular"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawablePadding="@dimen/cometchat_padding_2"
            android:gravity="center_vertical"
            android:paddingStart="@dimen/cometchat_padding_4"
            android:paddingTop="@dimen/cometchat_padding_2"
            android:paddingEnd="@dimen/cometchat_padding_4"
            android:paddingBottom="@dimen/cometchat_padding_2"
            android:textAppearance="?attr/textAppearanceSubtitle1"
            android:textColor="?attr/cometchatTextColorPrimary"
            app:drawableStartCompat="@drawable/ic_user_profile" />

        <TextView
            android:id="@+id/tv_logout"
            style="?attr/cometchatTextAppearanceBodyRegular"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawablePadding="@dimen/cometchat_padding_2"
            android:gravity="center_vertical"
            android:paddingStart="@dimen/cometchat_padding_4"
            android:paddingTop="@dimen/cometchat_padding_2"
            android:paddingEnd="@dimen/cometchat_padding_4"
            android:paddingBottom="@dimen/cometchat_padding_2"
            android:text="@string/app_logout"
            android:textAppearance="?attr/textAppearanceSubtitle1"
            android:textColor="?attr/cometchatErrorColor"
            app:drawableStartCompat="@drawable/ic_logout" />

        <View
            android:layout_width="match_parent"
            android:layout_height="@dimen/cometchat_1dp"
            android:layout_gravity="center"
            android:background="?attr/cometchatStrokeColorDefault" />

        <TextView
            android:id="@+id/tv_version"
            style="?attr/cometchatTextAppearanceBodyRegular"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:padding="@dimen/cometchat_padding_4"
            android:textAppearance="?attr/textAppearanceCaption"
            android:textColor="?attr/cometchatTextColorSecondary" />

    </LinearLayout>

</com.google.android.material.card.MaterialCardView>
```

> **What this does:** Defines a popup menu layout with options for creating a conversation, viewing the user profile, logging out, and displaying the app version.

Inflate the view and pass it to `setOverflowMenu`:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    class YourActivity : AppCompatActivity() {
        private lateinit var cometChatConversations: CometChatConversations

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            cometChatConversations = findViewById(R.id.conversations)
            cometChatConversations.setOverflowMenu(logoutView)
        }

        private val logoutView: View?
            get() {
                val user = CometChatUIKit.getLoggedInUser()
                if (user != null) {
                    val cometchatAvatar = CometChatAvatar(this)
                    cometchatAvatar.setAvatar(user.name, user.avatar)
                    val layoutParams = LinearLayout.LayoutParams(
                        resources.getDimensionPixelSize(com.cometchat.chatuikit.R.dimen.cometchat_40dp),
                        resources.getDimensionPixelSize(com.cometchat.chatuikit.R.dimen.cometchat_40dp))
                    layoutParams.layoutDirection = Gravity.CENTER_VERTICAL
                    cometchatAvatar.layoutParams = layoutParams
                    cometchatAvatar.setOnClickListener {
                        showCustomMenu(cometChatConversations.binding.toolbarLayout)
                    }
                    return cometchatAvatar
                }
                return null
            }

        private fun showCustomMenu(anchorView: View) {
            val popupMenuBinding = UserProfilePopupMenuLayoutBinding.inflate(LayoutInflater.from(this))
            val popupWindow = PopupWindow(popupMenuBinding.root,
                resources.getDimensionPixelSize(com.cometchat.chatuikit.R.dimen.cometchat_250dp),
                LinearLayout.LayoutParams.WRAP_CONTENT, true)

            popupMenuBinding.tvUserName.text = CometChatUIKit.getLoggedInUser().name
            val version = "V" + BuildConfig.VERSION_NAME + "(" + BuildConfig.VERSION_CODE + ")"
            popupMenuBinding.tvVersion.text = version

            popupMenuBinding.tvCreateConversation.setOnClickListener { popupWindow.dismiss() }
            popupMenuBinding.tvUserName.setOnClickListener { popupWindow.dismiss() }
            popupMenuBinding.tvLogout.setOnClickListener { popupWindow.dismiss() }

            popupWindow.elevation = 5f
            val endMargin = resources.getDimensionPixelSize(com.cometchat.chatuikit.R.dimen.cometchat_margin_2)
            val anchorWidth = anchorView.width
            val offsetX = anchorWidth - popupWindow.width - endMargin
            popupWindow.showAsDropDown(anchorView, offsetX, 0)
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    public class YourActivity extends AppCompatActivity {
        private CometChatConversations cometChatConversations;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            cometChatConversations = findViewById(R.id.conversations);
            cometChatConversations.setOverflowMenu(getLogoutView());
        }

        private View getLogoutView() {
            User user = CometChatUIKit.getLoggedInUser();
            if (user != null) {
                CometChatAvatar cometchatAvatar = new CometChatAvatar(this);
                cometchatAvatar.setAvatar(user.getName(), user.getAvatar());
                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                    getResources().getDimensionPixelSize(com.cometchat.chatuikit.R.dimen.cometchat_40dp),
                    getResources().getDimensionPixelSize(com.cometchat.chatuikit.R.dimen.cometchat_40dp));
                layoutParams.setLayoutDirection(Gravity.CENTER_VERTICAL);
                cometchatAvatar.setLayoutParams(layoutParams);
                cometchatAvatar.setOnClickListener(v -> {
                    showCustomMenu(cometChatConversations.getBinding().toolbarLayout);
                });
                return cometchatAvatar;
            }
            return null;
        }

        private void showCustomMenu(View anchorView) {
            UserProfilePopupMenuLayoutBinding popupMenuBinding = UserProfilePopupMenuLayoutBinding.inflate(LayoutInflater.from(this));
            final PopupWindow popupWindow = new PopupWindow(popupMenuBinding.getRoot(),
                getResources().getDimensionPixelSize(com.cometchat.chatuikit.R.dimen.cometchat_250dp),
                LinearLayout.LayoutParams.WRAP_CONTENT, true);

            popupMenuBinding.tvUserName.setText(CometChatUIKit.getLoggedInUser().getName());
            String version = "V" + BuildConfig.VERSION_NAME + "(" + BuildConfig.VERSION_CODE + ")";
            popupMenuBinding.tvVersion.setText(version);

            popupMenuBinding.tvCreateConversation.setOnClickListener(view -> popupWindow.dismiss());
            popupMenuBinding.tvUserName.setOnClickListener(view -> popupWindow.dismiss());
            popupMenuBinding.tvLogout.setOnClickListener(view -> popupWindow.dismiss());

            popupWindow.setElevation(5);
            int endMargin = getResources().getDimensionPixelSize(com.cometchat.chatuikit.R.dimen.cometchat_margin_2);
            int anchorWidth = anchorView.getWidth();
            int offsetX = anchorWidth - popupWindow.getWidth() - endMargin;
            popupWindow.showAsDropDown(anchorView, offsetX, 0);
        }
    }
    ```
  </Tab>
</Tabs>

> **What this does:** Creates a complete overflow menu implementation. An avatar of the logged-in user is set as the overflow menu view. When tapped, it shows a popup window with options for creating a conversation, viewing the user profile, logging out, and displaying the app version.

* **Verify**: After setting any custom view slot, confirm the custom view renders in the correct position within the conversation list item, and the data binding populates correctly for each conversation.

## Common Patterns

### Custom empty state with action button

```xml layout/empty_conversations.xml lines theme={null}
<?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:gravity="center"
    android:orientation="vertical"
    android:padding="40dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="No conversations yet"
        android:textAppearance="?attr/cometchatTextAppearanceHeading3Bold" />

    <Button
        android:id="@+id/btn_start_chat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Start a conversation" />

</LinearLayout>
```

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometChatConversations.emptyView = R.layout.empty_conversations
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometChatConversations.setEmptyView(R.layout.empty_conversations);
    ```
  </Tab>
</Tabs>

### Hide all chrome — minimal list

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometChatConversations.setReceiptsVisibility(View.GONE)
    cometChatConversations.setUserStatusVisibility(View.GONE)
    cometChatConversations.setGroupTypeVisibility(View.GONE)
    cometChatConversations.setDeleteConversationOptionVisibility(View.GONE)
    cometChatConversations.setToolbarVisibility(View.GONE)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometChatConversations.setReceiptsVisibility(View.GONE);
    cometChatConversations.setUserStatusVisibility(View.GONE);
    cometChatConversations.setGroupTypeVisibility(View.GONE);
    cometChatConversations.setDeleteConversationOptionVisibility(View.GONE);
    cometChatConversations.setToolbarVisibility(View.GONE);
    ```
  </Tab>
</Tabs>

### Filter to user conversations only

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = ConversationsRequest.ConversationsRequestBuilder()
        .setConversationType(CometChatConstants.CONVERSATION_TYPE_USER)
    cometChatConversations.setConversationsRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    ConversationsRequest.ConversationsRequestBuilder builder = new ConversationsRequest.ConversationsRequestBuilder();
    builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER);
    cometChatConversations.setConversationsRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

## Advanced Methods

### Programmatic Selection

#### `selectConversation`

Programmatically selects or deselects a conversation. Works with both `SINGLE` and `MULTIPLE` selection modes.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    // Select a conversation in single-select mode
    cometChatConversations.selectConversation(conversation, UIKitConstants.SelectionMode.SINGLE)

    // Select a conversation in multi-select mode
    cometChatConversations.selectConversation(conversation, UIKitConstants.SelectionMode.MULTIPLE)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    // Select a conversation in single-select mode
    cometChatConversations.selectConversation(conversation, UIKitConstants.SelectionMode.SINGLE);

    // Select a conversation in multi-select mode
    cometChatConversations.selectConversation(conversation, UIKitConstants.SelectionMode.MULTIPLE);
    ```
  </Tab>
</Tabs>

> In `SINGLE` mode, selecting a new conversation replaces the previous selection. In `MULTIPLE` mode, calling this on an already-selected conversation deselects it (toggle behavior).

#### `clearSelection`

Clears all selected conversations and resets the selection UI.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometChatConversations.clearSelection()
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometChatConversations.clearSelection();
    ```
  </Tab>
</Tabs>

#### `getSelectedConversations`

Returns the list of currently selected `Conversation` objects.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val selected = cometChatConversations.selectedConversations
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    List<Conversation> selected = cometChatConversations.getSelectedConversations();
    ```
  </Tab>
</Tabs>

### Selected Conversations List

When using multi-select mode, a horizontal list of selected conversations can be shown above the main list.

| Method                                      | Type                             | Description                                     |
| ------------------------------------------- | -------------------------------- | ----------------------------------------------- |
| `setSelectedConversationsListVisibility`    | `int (View.VISIBLE / View.GONE)` | Show or hide the selected conversations strip   |
| `setSelectedConversationAvatarStyle`        | `@StyleRes int`                  | Avatar style for selected conversation chips    |
| `setSelectedConversationItemTextColor`      | `@ColorInt int`                  | Text color for selected conversation names      |
| `setSelectedConversationItemTextAppearance` | `@StyleRes int`                  | Text appearance for selected conversation names |
| `setSelectedConversationItemRemoveIcon`     | `Drawable`                       | Icon for the remove button on each chip         |
| `setSelectedConversationItemRemoveIconTint` | `@ColorInt int`                  | Tint color for the remove icon                  |

### Search Input Customization

The built-in search box can be customized programmatically:

| Method                                    | Type             | Description                                    |
| ----------------------------------------- | ---------------- | ---------------------------------------------- |
| `setSearchInputText`                      | `String`         | Sets the search input text programmatically    |
| `setSearchPlaceholderText`                | `String`         | Sets the placeholder text for the search input |
| `setSearchInputTextColor`                 | `@ColorInt int`  | Text color of the search input                 |
| `setSearchInputTextAppearance`            | `@StyleRes int`  | Text appearance of the search input            |
| `setSearchInputPlaceHolderTextColor`      | `@ColorInt int`  | Placeholder text color                         |
| `setSearchInputPlaceHolderTextAppearance` | `@StyleRes int`  | Placeholder text appearance                    |
| `setSearchInputStartIcon`                 | `Drawable`       | Leading icon in the search box                 |
| `setSearchInputStartIconTint`             | `@ColorInt int`  | Tint for the leading icon                      |
| `setSearchInputEndIcon`                   | `Drawable`       | Trailing icon in the search box                |
| `setSearchInputEndIconTint`               | `@ColorInt int`  | Tint for the trailing icon                     |
| `setSearchInputEndIconVisibility`         | `int`            | Visibility of the trailing icon                |
| `setSearchInputStrokeWidth`               | `@Dimension int` | Stroke width of the search box border          |
| `setSearchInputStrokeColor`               | `@ColorInt int`  | Stroke color of the search box border          |
| `setSearchInputBackgroundColor`           | `@ColorInt int`  | Background color of the search box             |
| `setSearchInputCornerRadius`              | `@Dimension int` | Corner radius of the search box                |

### Internal Access

These methods provide direct access to internal components for advanced use cases.

| Method                             | Returns                                 | Description                                          |
| ---------------------------------- | --------------------------------------- | ---------------------------------------------------- |
| `getRecyclerView()`                | `RecyclerView`                          | The underlying RecyclerView displaying conversations |
| `getViewModel()`                   | `ConversationsViewModel`                | The ViewModel managing conversation data and state   |
| `getConversationsAdapter()`        | `ConversationsAdapter`                  | The adapter powering the RecyclerView                |
| `setAdapter(ConversationsAdapter)` | `void`                                  | Replaces the default adapter with a custom one       |
| `getBinding()`                     | `CometchatConversationsListViewBinding` | The ViewBinding for the component's root layout      |

> Use these only when the standard API is insufficient. Directly manipulating the adapter or ViewModel may conflict with the component's internal state management.

### Other Methods

| Method                                                    | Type   | Description                                                     |
| --------------------------------------------------------- | ------ | --------------------------------------------------------------- |
| `setMentionAllLabelId(String id, String mentionAllLabel)` | `void` | Sets the label used for "mention all" in conversation subtitles |
| `setDateStyle(@StyleRes int)`                             | `void` | Sets the style for the date label in conversation items         |
| `setOptionListStyle(@StyleRes int)`                       | `void` | Sets the style for the long-press popup menu                    |

## Style

The component uses XML theme styles. Define a custom style with parent `CometChatConversationsStyle` in `themes.xml`, then apply with `setStyle()`.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-agent-in-group-react-v6/BRVNF1Z1yHcA0g5c/images/433c987e-Conversation_Styling-1e5686a26eb349d5cbc40262b9b6df0e.png?fit=max&auto=format&n=BRVNF1Z1yHcA0g5c&q=85&s=dcfdf6ce284baa828774431460a153b0" width="1280" height="800" data-path="images/433c987e-Conversation_Styling-1e5686a26eb349d5cbc40262b9b6df0e.png" />
</Frame>

```xml themes.xml lines theme={null}
    <style name="CustomAvatarStyle" parent="CometChatAvatarStyle">
        <item name="cometchatAvatarStrokeRadius">8dp</item>
        <item name="cometchatAvatarBackgroundColor">#FBAA75</item>
    </style>

    <style name="CustomBadgeCountStyle" parent="CometChatBadgeStyle">
        <item name="cometchatBadgeBackgroundColor">#F76808</item>
        <item name="cometchatBadgeTextColor">#FFFFFF</item>
    </style>

    <style name="CustomConversationsStyle" parent="CometChatConversationsStyle">
        <item name="cometchatConversationsAvatarStyle">@style/CustomAvatarStyle</item>
        <item name="cometchatConversationsBadgeStyle">@style/CustomBadgeCountStyle</item>
    </style>
```

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometChatConversations.setStyle(R.style.CustomConversationsStyle)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometChatConversations.setStyle(R.style.CustomConversationsStyle);
    ```
  </Tab>
</Tabs>

To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_conversations.xml).

### Programmatic Style Properties

In addition to XML theme styles, the component exposes programmatic setters for fine-grained control:

| Method                                | Type             | Description                                     |
| ------------------------------------- | ---------------- | ----------------------------------------------- |
| `setBackgroundColor`                  | `@ColorInt int`  | Background color of the component               |
| `setBackIconTint`                     | `@ColorInt int`  | Tint color for the back icon                    |
| `setBackIcon`                         | `Drawable`       | Custom back icon drawable                       |
| `setTitleTextColor`                   | `@ColorInt int`  | Title text color in the toolbar                 |
| `setTitleTextAppearance`              | `@StyleRes int`  | Title text appearance in the toolbar            |
| `setItemTitleTextColor`               | `@ColorInt int`  | Text color for conversation item titles         |
| `setItemTitleTextAppearance`          | `@StyleRes int`  | Text appearance for conversation item titles    |
| `setItemSubtitleTextColor`            | `@ColorInt int`  | Text color for conversation item subtitles      |
| `setItemSubtitleTextAppearance`       | `@StyleRes int`  | Text appearance for conversation item subtitles |
| `setItemMessageTypeIconTint`          | `@ColorInt int`  | Tint for message type icons in subtitles        |
| `setSeparatorColor`                   | `@ColorInt int`  | Color of list item separators                   |
| `setSeparatorHeight`                  | `@Dimension int` | Height of list item separators                  |
| `setStrokeColor`                      | `@ColorInt int`  | Stroke color of the component border            |
| `setStrokeWidth`                      | `@Dimension int` | Stroke width of the component border            |
| `setCornerRadius`                     | `@Dimension int` | Corner radius of the component                  |
| `setEmptyStateTitleTextColor`         | `@ColorInt int`  | Title text color for the empty state            |
| `setEmptyStateSubtitleTextColor`      | `@ColorInt int`  | Subtitle text color for the empty state         |
| `setEmptyStateTextTitleAppearance`    | `@StyleRes int`  | Title text appearance for the empty state       |
| `setEmptyStateTextSubtitleAppearance` | `@StyleRes int`  | Subtitle text appearance for the empty state    |
| `setErrorStateTitleTextColor`         | `@ColorInt int`  | Title text color for the error state            |
| `setErrorStateSubtitleTextColor`      | `@ColorInt int`  | Subtitle text color for the error state         |
| `setErrorStateTextTitleAppearance`    | `@StyleRes int`  | Title text appearance for the error state       |
| `setErrorStateTextSubtitleAppearance` | `@StyleRes int`  | Subtitle text appearance for the error state    |
| `setDeleteOptionIcon`                 | `Drawable`       | Icon for the delete option in the context menu  |
| `setDeleteOptionIconTint`             | `int`            | Tint for the delete option icon                 |
| `setDeleteOptionTextColor`            | `int`            | Text color for the delete option                |
| `setDeleteOptionTextAppearance`       | `int`            | Text appearance for the delete option           |
| `setAvatarStyle`                      | `@StyleRes int`  | Style for conversation avatars                  |
| `setStatusIndicatorStyle`             | `@StyleRes int`  | Style for online/offline status indicators      |
| `setBadgeStyle`                       | `@StyleRes int`  | Style for unread badge counts                   |
| `setReceiptStyle`                     | `@StyleRes int`  | Style for read/delivered receipt icons          |
| `setTypingIndicatorStyle`             | `@StyleRes int`  | Style for typing indicator text                 |
| `setMentionsStyle`                    | `@StyleRes int`  | Style for @mention text in subtitles            |
| `setItemBackgroundColor`              | `@ColorInt int`  | Background color for list items                 |
| `setItemSelectedBackgroundColor`      | `@ColorInt int`  | Background color for selected list items        |

### Checkbox Style Properties (Selection Mode)

When using `SINGLE` or `MULTIPLE` selection mode, checkboxes appear on each item:

| Method                              | Type             | Description                            |
| ----------------------------------- | ---------------- | -------------------------------------- |
| `setCheckBoxStrokeWidth`            | `@Dimension int` | Stroke width of the checkbox border    |
| `setCheckBoxCornerRadius`           | `@Dimension int` | Corner radius of the checkbox          |
| `setCheckBoxStrokeColor`            | `@ColorInt int`  | Stroke color of the checkbox border    |
| `setCheckBoxBackgroundColor`        | `@ColorInt int`  | Background color of unchecked checkbox |
| `setCheckBoxCheckedBackgroundColor` | `@ColorInt int`  | Background color of checked checkbox   |
| `setCheckBoxSelectIcon`             | `Drawable`       | Icon shown when checkbox is checked    |
| `setCheckBoxSelectIconTint`         | `@ColorInt int`  | Tint for the checkbox select icon      |
| `setDiscardSelectionIcon`           | `Drawable`       | Icon for the discard selection button  |
| `setDiscardSelectionIconTint`       | `@ColorInt int`  | Tint for the discard selection icon    |
| `setSubmitSelectionIcon`            | `Drawable`       | Icon for the submit selection button   |
| `setSubmitSelectionIconTint`        | `@ColorInt int`  | Tint for the submit selection icon     |

## Customization Matrix

| What to change                             | Where             | Property/API                                                  | Example                                                                         |
| ------------------------------------------ | ----------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| Override behavior on user interaction      | Activity/Fragment | `setOn<Event>` callbacks                                      | `setOnItemClick((v, pos, c) -> { ... })`                                        |
| Filter which conversations appear          | Activity/Fragment | `setConversationsRequestBuilder`                              | `setConversationsRequestBuilder(builder)`                                       |
| Toggle visibility of UI elements           | Activity/Fragment | `set<Feature>Visibility(int)`                                 | `setReceiptsVisibility(View.GONE)`                                              |
| Replace a section of the list item         | Activity/Fragment | `set<Slot>View`                                               | `setLeadingView(listener)`                                                      |
| Change colors, fonts, spacing              | `themes.xml`      | `CometChatConversationsStyle`                                 | `<item name="cometchatConversationsBadgeStyle">@style/...</item>`               |
| Avatar style (corner radius, background)   | `themes.xml`      | `cometchatConversationsAvatarStyle`                           | `<item name="cometchatAvatarStrokeRadius">8dp</item>`                           |
| Badge count style (background, text color) | `themes.xml`      | `cometchatConversationsBadgeStyle`                            | `<item name="cometchatBadgeBackgroundColor">#F76808</item>`                     |
| Apply a custom style                       | Activity/Fragment | `setStyle(int styleRes)`                                      | `cometChatConversations.setStyle(R.style.CustomConversationsStyle);`            |
| Back button visibility                     | Activity/Fragment | `setBackIconVisibility(int)`                                  | `.setBackIconVisibility(View.VISIBLE);`                                         |
| Toolbar visibility                         | Activity/Fragment | `setToolbarVisibility(int)`                                   | `.setToolbarVisibility(View.GONE);`                                             |
| Loading state visibility                   | Activity/Fragment | `setLoadingStateVisibility(int)`                              | `.setLoadingStateVisibility(View.GONE);`                                        |
| Delete option visibility on long press     | Activity/Fragment | `setDeleteConversationOptionVisibility(int)`                  | `.setDeleteConversationOptionVisibility(View.GONE);`                            |
| Error state visibility                     | Activity/Fragment | `setErrorStateVisibility(int)`                                | `.setErrorStateVisibility(View.GONE);`                                          |
| Empty state visibility                     | Activity/Fragment | `setEmptyStateVisibility(int)`                                | `.setEmptyStateVisibility(View.GONE);`                                          |
| Separator visibility                       | Activity/Fragment | `setSeparatorVisibility(int)`                                 | `.setSeparatorVisibility(View.GONE);`                                           |
| User online status visibility              | Activity/Fragment | `setUserStatusVisibility(int)`                                | `.setUserStatusVisibility(View.GONE);`                                          |
| Group type indicator visibility            | Activity/Fragment | `setGroupTypeVisibility(int)`                                 | `.setGroupTypeVisibility(View.GONE);`                                           |
| Read/delivered receipts visibility         | Activity/Fragment | `setReceiptsVisibility(int)`                                  | `.setReceiptsVisibility(View.GONE);`                                            |
| Incoming message sound                     | Activity/Fragment | `disableSoundForMessages(boolean)`                            | `.disableSoundForMessages(true);`                                               |
| Custom message sound                       | Activity/Fragment | `setCustomSoundForMessages(int)`                              | `.setCustomSoundForMessages(R.raw.cometchat_beep2);`                            |
| Selection mode (single/multiple)           | Activity/Fragment | `setSelectionMode(SelectionMode)`                             | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);`                     |
| Date/time formatting                       | Activity/Fragment | `setDateTimeFormatter(DateTimeFormatterCallback)`             | See `setDateTimeFormatter` code above                                           |
| Date format                                | Activity/Fragment | `setDateFormat(SimpleDateFormat)`                             | `.setDateFormat(new SimpleDateFormat("dd MMM, hh:mm a", Locale.getDefault()));` |
| Long-press options (replace)               | Activity/Fragment | `setOptions(Function2)`                                       | See `setOptions` code above                                                     |
| Long-press options (append)                | Activity/Fragment | `addOptions(Function2)`                                       | See `addOptions` code above                                                     |
| Loading view                               | Activity/Fragment | `setLoadingView(int)`                                         | `.setLoadingView(R.layout.your_loading_view);`                                  |
| Empty view                                 | Activity/Fragment | `setEmptyView(int)`                                           | `.setEmptyView(R.layout.your_empty_view);`                                      |
| Error view                                 | Activity/Fragment | `setErrorView(int)`                                           | `.setErrorView(R.layout.your_error_view);`                                      |
| Leading view (avatar area)                 | Activity/Fragment | `setLeadingView(ConversationsViewHolderListener)`             | See `setLeadingView` code above                                                 |
| Title view                                 | Activity/Fragment | `setTitleView(ConversationsViewHolderListener)`               | See `setTitleView` code above                                                   |
| Trailing view                              | Activity/Fragment | `setTrailingView(ConversationsViewHolderListener)`            | See `setTrailingView` code above                                                |
| Entire list item                           | Activity/Fragment | `setItemView(ConversationsViewHolderListener)`                | See `setItemView` code above                                                    |
| Subtitle view                              | Activity/Fragment | `setSubtitleView(ConversationsViewHolderListener)`            | See `setSubtitleView` code above                                                |
| Text formatters (mentions)                 | Activity/Fragment | `setTextFormatters(List<CometChatTextFormatter>)`             | See `setTextFormatters` code above                                              |
| Overflow menu                              | Activity/Fragment | `setOverflowMenu(View)`                                       | `cometChatConversations.setOverflowMenu(view);`                                 |
| Filter conversations                       | Activity/Fragment | `setConversationsRequestBuilder(ConversationsRequestBuilder)` | See Filters code above                                                          |
| Search box visibility                      | Activity/Fragment | `setSearchBoxVisibility(int)`                                 | `.setSearchBoxVisibility(View.GONE);`                                           |
| Search input text                          | Activity/Fragment | `setSearchInputText(String)`                                  | `.setSearchInputText("search term");`                                           |
| Search placeholder text                    | Activity/Fragment | `setSearchPlaceholderText(String)`                            | `.setSearchPlaceholderText("Search...");`                                       |
| Search input colors                        | Activity/Fragment | `setSearchInputTextColor`, `setSearchInputBackgroundColor`    | `.setSearchInputTextColor(Color.BLACK);`                                        |
| Search input icons                         | Activity/Fragment | `setSearchInputStartIcon`, `setSearchInputEndIcon`            | `.setSearchInputStartIcon(drawable);`                                           |
| Hide receipts (adapter)                    | Activity/Fragment | `hideReceipts(boolean)`                                       | `.hideReceipts(true);`                                                          |
| Programmatic selection                     | Activity/Fragment | `selectConversation(Conversation, SelectionMode)`             | `.selectConversation(conv, SelectionMode.SINGLE);`                              |
| Clear selection                            | Activity/Fragment | `clearSelection()`                                            | `.clearSelection();`                                                            |
| Selected conversations strip               | Activity/Fragment | `setSelectedConversationsListVisibility(int)`                 | `.setSelectedConversationsListVisibility(View.VISIBLE);`                        |
| Selected conversation avatar style         | Activity/Fragment | `setSelectedConversationAvatarStyle(int)`                     | `.setSelectedConversationAvatarStyle(R.style.CustomAvatarStyle);`               |
| Internal adapter access                    | Activity/Fragment | `getConversationsAdapter()` / `setAdapter()`                  | Advanced use only                                                               |
| Internal ViewModel access                  | Activity/Fragment | `getViewModel()`                                              | Advanced use only                                                               |
| Mention-all label                          | Activity/Fragment | `setMentionAllLabelId(String, String)`                        | `.setMentionAllLabelId("all", "Everyone");`                                     |

## Next Steps

<CardGroup cols={2}>
  <Card title="Users" icon="user" href="/ui-kit/android/users">
    Browse and search available users
  </Card>

  <Card title="Groups" icon="users" href="/ui-kit/android/groups">
    Browse and search available groups
  </Card>

  <Card title="Message List" icon="messages" href="/ui-kit/android/message-list">
    Display messages in a conversation
  </Card>

  <Card title="Message Composer" icon="pen-to-square" href="/ui-kit/android/message-composer">
    Rich input for sending messages
  </Card>
</CardGroup>
