Skip to main content
CometChatConversations displays all conversations for the currently logged-in user, showing recent messages, user or group details, and unread counts.

When to use this

  • You need a screen that lists all one-on-one and group conversations for the logged-in user.
  • You want to show the last message, unread badge count, and user/group avatar for each conversation.
  • You need tap and long-press actions on conversation items (open chat, delete, pin, mute).
  • You want to filter conversations by type (user or group), tags, or custom request builders.
  • You need real-time updates when conversations are deleted or modified.
  • You want to customize the conversation list appearance with styles, custom views, or text formatters.

Prerequisites

  • CometChat SDK initialized with CometChatUIKit.init() and a user logged in.
  • The cometchat-chat-uikit-android dependency added to your project.
  • A valid layout_activity.xml or Activity/Fragment where you will place the component.

Quick start

  1. Open your layout_activity.xml file.
  2. Add the CometChatConversations XML element:
layout_activity.xml
<com.cometchat.chatuikit.conversations.CometChatConversations
        android:id="@+id/conversation"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
What this does: Adds the CometChatConversations component to your layout. It fills the available width and height and renders the conversation list for the logged-in user.
  1. Build and run your app.
  2. Verify that the conversation list appears with avatars, names, last messages, and unread badges.
  1. If you need to add the component programmatically instead of XML, see the Activity integration or Fragment integration subsections in Implementation.

Core concepts

  • CometChatConversations: The main component class that renders the conversation list. It can be added via XML layout, Activity, or Fragment.
  • Actions: Callbacks such as setOnItemClick, setOnItemLongClick, and setOnBackPressListener that let you respond to user interactions.
  • Filters: Use ConversationsRequest.ConversationsRequestBuilder to filter conversations by type, limit, tags, user tags, or group tags.
  • Events: Global events emitted by the component (e.g., ccConversationDeleted) that you can listen to from anywhere in your app using CometChatConversationEvents.
  • Style: XML theme styles (parent CometChatConversationsStyle) applied via setStyle() to customize colors, fonts, and sub-component styles.
  • Advanced views: Methods like setLeadingView, setTitleView, setTrailingView, setItemView, and setSubtitleView that let you replace default UI elements with custom layouts.

Implementation

Activity integration

What you’re changing: How you add CometChatConversations to an Activity programmatically.
  • Where: Your Activity class (e.g., YourActivity.java or YourActivity.kt).
  • Applies to: CometChatConversations.
  • Default behavior: The component is not added until you set it as the content view.
  • Override: Call setContentView(new CometChatConversations(this)) in onCreate.
  • Code:
YourActivity.java
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       setContentView(new CometChatConversations(this));
    }
What this does: Creates a new CometChatConversations instance and sets it as the entire content view of the Activity. The conversation list renders immediately after the Activity is created.
  • Verify: The conversation list fills the screen when the Activity launches.

Fragment integration

What you’re changing: How you add CometChatConversations to a Fragment.
  • Where: Your Fragment class (e.g., YourFragment.java or YourFragment.kt).
  • Applies to: CometChatConversations.
  • Default behavior: The component is not added until you return it from onCreateView.
  • Override: Return new CometChatConversations(getContext()) from onCreateView.
  • Code:
YourFragment.java
@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
       return new CometChatConversations(getContext());
    }
What this does: Creates a new CometChatConversations instance and returns it as the Fragment’s root view. The conversation list renders when the Fragment is displayed.
  • Verify: The conversation list appears inside the Fragment’s container.

Actions

What you’re changing: How the component responds to user interactions such as taps, long-presses, back button, selection, errors, load completion, and empty states.
  • Where: Activity or Fragment where you hold a reference to CometChatConversations (e.g., cometchatConversations).
  • Applies to: CometChatConversations.
  • Default behavior: Predefined actions execute automatically (e.g., tapping a conversation opens the chat, pressing back navigates to the previous screen).
  • Override: Call the corresponding setter method to replace the default behavior with your own logic.

setOnItemClick

Function invoked when a conversation item is clicked, used to open a detailed chat screen.
YourActivity.java
cometchatConversations.setOnItemClick((view1, position, conversation) -> {
            
    });
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

Function executed when a conversation item is long-pressed, allowing additional actions like delete or select.
YourActivity.java
cometchatConversations.setOnItemLongClick((view1, position, conversation) -> {

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

setOnBackPressListener

Triggered when the user presses the back button in the app bar. By default, it navigates to the previous activity.
YourActivity.java
cometchatConversations.setOnBackPressListener(() -> {
            
    });
What this does: Overrides the default back-press navigation. When the user taps the back button, your custom logic runs instead.

setOnSelect

Called when an item from the fetched list is selected, useful for multi-selection features.
YourActivity.java
cometchatConversations.setOnSelect(t -> {

    });
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

Listens for any errors that occur in the Conversations component. This does not change the component’s behavior.
YourActivity.java
cometchatConversations.setOnError(cometchatException -> {

    });
What this does: Registers an error listener. If the component encounters an error (e.g., network failure), your callback receives the CometChatException.

setOnLoad

Invoked when the list is successfully fetched and loaded, helping track component readiness.
YourActivity.java
cometchatConversations.setOnLoad(list -> {

});
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

Called when the list is empty, enabling custom handling such as showing a placeholder message.
YourActivity.java
cometchatConversations.setOnEmpty(() -> {
            
    });
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.
  • Verify: After setting an action callback, trigger the corresponding user interaction (tap, long-press, back, select) and confirm your custom logic executes instead of the default behavior.

Filters

What you’re changing: Which conversations appear in the list.
  • Where: Activity or Fragment where you hold a reference to CometChatConversations.
  • Applies to: CometChatConversations.
  • Default behavior: All conversations for the logged-in user are fetched and displayed.
  • Override: Create a ConversationsRequest.ConversationsRequestBuilder, configure it, and pass it to setConversationsRequestBuilder.
You can filter using the following parameters:
  1. Conversation Type: Filters on type of Conversation, User or Groups.
  2. Limit: Number of conversations fetched in a single request.
  3. WithTags: Filter on fetching conversations containing tags.
  4. Tags: Filters on specific Tag.
  5. UserTags: Filters on specific User Tag.
  6. GroupTags: Filters on specific Group Tag.
  • Code:
YourActivity.java
ConversationsRequest.ConversationsRequestBuilder builder = new ConversationsRequest.ConversationsRequestBuilder();
            builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER);
            builder.setLimit(50);

cometChatConversations.setConversationsRequestBuilder(builder);
What this does: Creates a ConversationsRequestBuilder that filters conversations to show only user (one-on-one) conversations with a limit of 50 per fetch. The builder is then applied to the CometChatConversations component.
  • Verify: The conversation list shows only user conversations (no group conversations) and fetches at most 50 items per request.

Events

What you’re changing: How your app reacts to global events emitted by the Conversations component.
  • Where: Any Activity, Fragment, or class where you want to listen for conversation events.
  • Applies to: CometChatConversationEvents.
  • Default behavior: No external listeners are registered. Events are emitted but not handled outside the component.
  • Override: Add a listener using CometChatConversationEvents.addListener and remove it when no longer needed using CometChatConversationEvents.removeListener.

ConversationDeleted

This event is emitted when the user deletes a conversation.
  • Code:
Add Listener
CometChatConversationEvents.addListener("YOUR_LISTENER_TAG", new CometChatConversationEvents() {
    @Override
    public void ccConversationDeleted(Conversation conversation) {
        super.ccConversationDeleted(conversation);
    }
});
Remove Listener
CometChatConversationEvents.removeListener("YOUR_LISTENER_TAG");
What this does: Registers a global event listener tagged with your identifier. When a conversation is deleted, the ccConversationDeleted callback fires with the deleted Conversation object. Call removeListener with the same tag to unsubscribe.
  • Verify: Delete a conversation in the UI and confirm your ccConversationDeleted callback fires with the correct Conversation object.

Style

What you’re changing: The visual appearance of the Conversations component using XML theme styles.
  • Where: themes.xml for style definitions, and your Activity/Fragment for applying the style.
  • Applies to: CometChatConversations.
  • Default behavior: The component uses the default CometChatConversationsStyle.
  • Override: Define a custom style with parent CometChatConversationsStyle in themes.xml, then call setStyle() on the component.
  • Code:
themes.xml
    <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>
What this does: Defines three custom styles: CustomAvatarStyle sets the avatar corner radius to 8dp and background color to #FBAA75; CustomBadgeCountStyle sets the badge background to #F76808 with white text; CustomConversationsStyle applies both sub-styles to the conversations component.
cometChatConversations.setStyle(R.style.CustomConversationsStyle);
What this does: Applies the CustomConversationsStyle theme to the CometChatConversations component, changing the avatar and badge appearance.
To know more such attributes, visit the attributes file.
  • Verify: The conversation list avatars display with rounded corners (8dp radius) and an orange background (#FBAA75), and unread badges show an orange background (#F76808) with white text.

Functionality

What you’re changing: Small functional customizations such as toggling visibility of UI elements, setting custom sounds, and configuring selection modes.
  • Where: Activity or Fragment where you hold a reference to CometChatConversations.
  • Applies to: CometChatConversations.
  • Default behavior: All UI elements are visible with default settings.
  • Override: Call the corresponding method on the component instance.
MethodsDescriptionCode
setBackIconVisibilityToggles visibility for the back button in the app bar.setBackIconVisibility(View.VISIBLE);
setToolbarVisibilityToggles visibility for the toolbar in the app bar.setToolbarVisibility(View.GONE);
setLoadingStateVisibilityHides the loading state while fetching conversations.setLoadingStateVisibility(View.GONE);
setDeleteConversationOptionVisibilityToggles visibility for the delete option on long press.setDeleteConversationOptionVisibility(View.GONE);
setErrorStateVisibilityHides the error state on fetching conversations.setErrorStateVisibility(View.GONE);
setEmptyStateVisibilityHides the empty state on fetching conversations.setEmptyStateVisibility(View.GONE);
setSeparatorVisibilityControls visibility of separators in the list view.setSeparatorVisibility(View.GONE);
setUsersStatusVisibilityControls visibility of the online status indicator.setUsersStatusVisibility(View.GONE);
setGroupTypeVisibilityControls visibility of the group type indicator.setGroupTypeVisibility(View.GONE);
setReceiptsVisibilityHides receipts shown in the subtitle without disabling read/delivered marking.setReceiptsVisibility(View.GONE);
disableSoundForMessagesDisables sound notifications for incoming messages.disableSoundForMessages(true);
setCustomSoundForMessagesSets a custom sound file for incoming message notifications.setCustomSoundForMessages(com.cometchat.chatuikit.R.raw.cometchat_beep2);
setSelectionModeDetermines the selection mode (single or multiple).setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);
  • 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.

Advanced views

What you’re changing: The default UI elements of conversation list items and the component’s chrome (loading, empty, error states, overflow menu, date formatting, text formatting).
  • Where: Activity or Fragment where you hold a reference to CometChatConversations.
  • Applies to: CometChatConversations.
  • Default behavior: The component renders its built-in views for each part of the conversation item and component chrome.
  • Override: Call the corresponding setter method and provide a custom view or callback.

setDateTimeFormatter

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


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";
        }
    });
What this does: Overrides the default date/time formatting for conversation timestamps. Today’s messages show “Today”, yesterday’s show “Yesterday”, recent messages show “X mins ago” or “X hrs ago”, last week’s show “Last Week”, and older messages show the full date in “dd MMM yyyy” format.

setOptions

Sets a predefined list of actions that users can perform when they long press a conversation in the list. This replaces the default options entirely.
cometchatConversations.setOptions((context, conversation) -> Collections.emptyList());
What this does: Replaces the default long-press options with an empty list, effectively removing all long-press menu items.
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;
        });
What this does: Replaces the default long-press options with a single “Delete” menu item. The item uses the error color from the theme and shows a toast when tapped.

addOptions

Extends the existing set of long-press actions without removing the default ones.
cometchatConversations.addOptions((context, conversation) -> Collections.emptyList());
What this does: Appends an empty list to the existing long-press options, leaving the defaults unchanged. Replace the empty list with your custom MenuItem objects to add new actions.
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, "Delete", 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, "Archive", 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;
        });
What this does: Appends three custom menu items (Archive, Pin, Mark as read) to the existing default long-press options. Each item uses the primary text color from the theme and shows a toast when tapped.

setLoadingView

Sets a custom loading view displayed when data is being fetched.
cometchatConversations.setLoadingView(R.layout.your_loading_view);
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.
cometchatConversations.setEmptyView(R.layout.your_empty_view);
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.
cometchatConversations.setErrorView(R.layout.your_empty_view);
What this does: Replaces the default error state with your custom layout resource. The custom view displays when the component encounters an error during data fetching.

setLeadingView

Sets a custom leading view element that appears at the beginning of each conversation item (e.g., avatars with online/offline status indicators).
        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) {

            }
        });
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.
The following example shows a custom leading view with a chat-dots icon for typing indicators and an avatar with status indicator:
drawable/chat_dots.xml
<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 file to inflate in setLeadingView():
<?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>
What this does: Defines a custom layout with a CometChatAvatar and CometChatStatusIndicator for the normal state, and a hidden ImageView for the typing indicator icon. The layout switches between the two based on typing state.
Inflate the XML and initialize the views using the conversation objects in setLeadingView:
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;
                    }
                    Log.e(TAG, "bindView: " + typingIndicator.getSender().getUid());
                    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);
                    }
                }

            }
        });
What this does: Implements a custom leading view that shows a typing indicator icon (chat dots) when the other user is typing, and an avatar with online/offline status indicator otherwise. A CometChat.MessageListener tracks typing state in a HashMap, and the bindView method switches between the icon and avatar based on that state.

setTitleView

Overrides the default title view in the conversation list with a custom layout.
        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) {

            }
        });
What this does: Registers a ConversationsViewHolderListener that provides a custom view for the title area of each conversation item. createView inflates your layout, and bindView populates it with conversation data.
Create a custom_title_view.xml custom layout file to inflate in setTitleView():
<?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>
What this does: Defines a custom title view layout with an avatar, status indicator, and a hidden typing indicator icon.
Inflate the XML and initialize the views using the conversation objects in setTitleView:
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);
                }
            }
        });
What this does: Inflates a custom title view layout and populates it with the conversation name and user status message. If the conversation is a user conversation, the status message is shown; if it is a group conversation, the status is hidden.

setTrailingView

Customizes the trailing (end) view of a conversation item, used for action buttons or additional information such as time-since-last-message badges. Create a custom_tail_view.xml custom layout file to inflate in setTrailingView():
<?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 the XML and initialize the views using the conversation objects in setTrailingView:
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) {
                    // Convert seconds to milliseconds
                    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);

                // Check if the timestamp is within the last hour
                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"));
                    return;

                } 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"));
                    return;
                }

                // Check if the timestamp is within the last 24 hours
                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));
                }
            }
        });
What this does: Inflates a custom trailing view that displays a color-coded time badge showing how long ago the conversation was last updated. Messages within the last hour show purple (“Min ago”), messages within 10 hours show amber (“Hr ago”), and older messages show red (“Hr ago”).

setItemView

Assigns a completely custom list item design to the Conversations component, replacing the default layout entirely.
        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) {

            }
        });
What this does: Registers a ConversationsViewHolderListener that replaces the entire default conversation list item layout. createView inflates your custom layout, and bindView populates it with conversation data.
Create an item_converation_list.xml custom layout file to inflate in setListItemView():
<?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.cometchatavatar.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.cometchatstatusindicator.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 initialize the views using the conversation objects in setItemView:
YourActivity.java
        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);
            }
        });
What this does: Inflates a custom list item layout and populates it with the conversation avatar, name, and formatted date. The avatar uses the default CometChatAvatarStyle and the date is formatted as “hh:mm a” (e.g., “02:30 PM”).

setTextFormatters

Defines and applies text formatters that dynamically modify or transform message content before rendering it in the UI. See the MentionsFormatter Guide for more details.
themes.xml
<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>
What this does: Defines a custom mentions style where other-user mentions appear in pink (#D6409F) and self-mentions appear in green (#30A46C), both using the body-regular text appearance.

// Initialize CometChatMentionsFormatter
CometChatMentionsFormatter mentionFormatter = new CometChatMentionsFormatter(context);

//set style to customize conversation mention text
mentionFormatter.setConversationsMentionTextStyle(context, R.style.CustomConversationsMentionsStyle);

// This can be passed as an array of formatter in CometChatConversations by using setTextFormatters method.
List<CometChatTextFormatter> textFormatters = new ArrayList<>();
textFormatters.add(mentionFormatter);
cometChatConversations.setTextFormatters(textFormatters);
What this does: Creates a CometChatMentionsFormatter, applies the custom mentions style, adds it to a list of text formatters, and passes that list to the conversations component. Mentions in conversation subtitles render with the custom colors.

setOverflowMenu

Customizes the overflow menu within the Conversations component. This menu appears as a three-dot or hamburger icon and provides additional options.
    cometChatConversations.setOverflowMenu(View v);
What this does: Sets a custom View as the overflow menu in the conversations toolbar. Pass any view (e.g., an avatar, icon button) to replace the default overflow menu.
Create a view_menu.xml custom view file to inflate and pass to setOverflowMenu:
user_profile_popup_menu_layout.xml
<?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. Get child view references to handle click actions:

import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import androidx.appcompat.app.AppCompatActivity;
import com.cometchat.chat.models.User;
import com.cometchat.chatuikit.conversations.CometChatConversations;
import com.cometchat.chatuikit.shared.cometchatuikit.CometChatUIKit;
import com.cometchat.chatuikit.shared.views.cometchatavatar.CometChatAvatar;
import com.cometchat.sampleapp.java.BuildConfig;
import com.cometchat.sampleapp.java.R;
import com.cometchat.sampleapp.java.databinding.UserProfilePopupMenuLayoutBinding;

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(CometChatUIKit.getLoggedInUser().getName(), CometChatUIKit.getLoggedInUser().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;
        int offsetY = 0;
        popupWindow.showAsDropDown(anchorView, offsetX, offsetY);
    }

}
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. Each option dismisses the popup when clicked.

setDateFormat

Customizes the date format used for displaying timestamps in conversations.
cometChatConversations.setDateFormat(SimpleDateFormat)
What this does: Sets a custom SimpleDateFormat for conversation timestamps. Pass a format pattern such as “dd/MM/yyyy HH:mm”, “MMM dd, yyyy”, or “hh:mm a”.
cometchatConversations.setDatePattern(new SimpleDateFormat("dd Mmm, hh:mm a",Locale.getDefault()));
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.

setSubtitleView

Customizes the subtitle view of each conversation item. The subtitle displays additional information below the conversation title, such as the last message or typing indicators.
cometChatConversations.setSubtitleView()
What this does: Registers a custom subtitle view for conversation items. Override createView and bindView in the ConversationsViewHolderListener to provide your custom subtitle layout and data binding.
YourActivity.java
    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);
            }
        });
What this does: Replaces the default subtitle with a custom TextView that shows “Last Active at:” followed by the conversation’s last update timestamp formatted as “dd/mm/yyyy, HH:MM:SS” in black text.
  • Verify: After setting any advanced view, confirm the custom view renders in the correct position within the conversation list item, and the data binding populates correctly for each conversation.

Customization matrix

What you want to changeWhereProperty/APIExample
Avatar style (corner radius, background)themes.xmlCometChatConversationsStyle with cometchatConversationsAvatarStyle<item name="cometchatAvatarStrokeRadius">8dp</item>
Badge count style (background, text color)themes.xmlCometChatConversationsStyle with cometchatConversationsBadgeStyle<item name="cometchatBadgeBackgroundColor">#F76808</item>
Apply a custom styleActivity/FragmentsetStyle(int styleRes)cometChatConversations.setStyle(R.style.CustomConversationsStyle);
Back button visibilityActivity/FragmentsetBackIconVisibility(int).setBackIconVisibility(View.VISIBLE);
Toolbar visibilityActivity/FragmentsetToolbarVisibility(int).setToolbarVisibility(View.GONE);
Loading state visibilityActivity/FragmentsetLoadingStateVisibility(int).setLoadingStateVisibility(View.GONE);
Delete option visibility on long pressActivity/FragmentsetDeleteConversationOptionVisibility(int).setDeleteConversationOptionVisibility(View.GONE);
Error state visibilityActivity/FragmentsetErrorStateVisibility(int).setErrorStateVisibility(View.GONE);
Empty state visibilityActivity/FragmentsetEmptyStateVisibility(int).setEmptyStateVisibility(View.GONE);
Separator visibilityActivity/FragmentsetSeparatorVisibility(int).setSeparatorVisibility(View.GONE);
User online status visibilityActivity/FragmentsetUsersStatusVisibility(int).setUsersStatusVisibility(View.GONE);
Group type indicator visibilityActivity/FragmentsetGroupTypeVisibility(int).setGroupTypeVisibility(View.GONE);
Read/delivered receipts visibilityActivity/FragmentsetReceiptsVisibility(int).setReceiptsVisibility(View.GONE);
Incoming message soundActivity/FragmentdisableSoundForMessages(boolean).disableSoundForMessages(true);
Custom message soundActivity/FragmentsetCustomSoundForMessages(int).setCustomSoundForMessages(com.cometchat.chatuikit.R.raw.cometchat_beep2);
Selection mode (single/multiple)Activity/FragmentsetSelectionMode(SelectionMode).setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);
Date/time formattingActivity/FragmentsetDateTimeFormatter(DateTimeFormatterCallback)See setDateTimeFormatter code above
Date patternActivity/FragmentsetDatePattern(SimpleDateFormat)cometchatConversations.setDatePattern(new SimpleDateFormat("dd MMM, hh:mm a", Locale.getDefault()));
Long-press options (replace)Activity/FragmentsetOptions(Function2)See setOptions code above
Long-press options (append)Activity/FragmentaddOptions(Function2)See addOptions code above
Loading viewActivity/FragmentsetLoadingView(int)cometchatConversations.setLoadingView(R.layout.your_loading_view);
Empty viewActivity/FragmentsetEmptyView(int)cometchatConversations.setEmptyView(R.layout.your_empty_view);
Error viewActivity/FragmentsetErrorView(int)cometchatConversations.setErrorView(R.layout.your_empty_view);
Leading view (avatar area)Activity/FragmentsetLeadingView(ConversationsViewHolderListener)See setLeadingView code above
Title viewActivity/FragmentsetTitleView(ConversationsViewHolderListener)See setTitleView code above
Trailing viewActivity/FragmentsetTrailingView(ConversationsViewHolderListener)See setTrailingView code above
Entire list itemActivity/FragmentsetItemView(ConversationsViewHolderListener)See setItemView code above
Subtitle viewActivity/FragmentsetSubtitleView(ConversationsViewHolderListener)See setSubtitleView code above
Text formatters (mentions)Activity/FragmentsetTextFormatters(List<CometChatTextFormatter>)See setTextFormatters code above
Overflow menuActivity/FragmentsetOverflowMenu(View)cometChatConversations.setOverflowMenu(View v);
Filter conversationsActivity/FragmentsetConversationsRequestBuilder(ConversationsRequestBuilder)See Filters code above

Common pitfalls & fixes

PitfallFix
Component does not renderEnsure CometChatUIKit.init() is called and awaited before using any UI Kit component. If init() has not completed, the component will not load data.
Conversation list is empty despite having conversationsVerify that a user is logged in with CometChatUIKit.login() before displaying the component. The component fetches conversations for the logged-in user only.
Filters not appliedEnsure you call setConversationsRequestBuilder(builder) on the CometChatConversations instance after creating and configuring the builder.
Custom style not visibleVerify the style parent is CometChatConversationsStyle and that you call setStyle(R.style.YourStyle) on the component instance.
setOnItemClick not firingIf you set setSelectionMode to MULTIPLE, item clicks may be consumed by the selection logic. Set the selection mode to NONE if you need standard click behavior.
Event listener not receiving eventsEnsure you call CometChatConversationEvents.addListener with a unique tag. If you use the same tag as another listener, the previous one is replaced.
Typing indicator not showing in custom leading viewEnsure you add a CometChat.MessageListener to track typing events and update the typingIndicatorHashMap before calling setLeadingView.
Custom view returns null in createViewIf createView returns null, the default view is used. Return a valid inflated View to replace the default.
Sound still plays after disableSoundForMessages(true)Ensure you call disableSoundForMessages(true) before the component starts loading. If called after data is already loaded, it may not take effect for existing notifications.
Delete option still visible after hidingEnsure you call setDeleteConversationOptionVisibility(View.GONE) on the correct CometChatConversations instance.

FAQ

Q: How do I show only user conversations (no groups)? A: Create a ConversationsRequest.ConversationsRequestBuilder, call setConversationType(CometChatConstants.CONVERSATION_TYPE_USER), and pass it to setConversationsRequestBuilder. Q: Can I use CometChatConversations in both an Activity and a Fragment? A: Yes. In an Activity, call setContentView(new CometChatConversations(this)). In a Fragment, return new CometChatConversations(getContext()) from onCreateView. Q: How do I listen for conversation deletion events outside the component? A: Use CometChatConversationEvents.addListener("YOUR_TAG", ...) and override ccConversationDeleted. Call CometChatConversationEvents.removeListener("YOUR_TAG") to unsubscribe. Q: How do I customize the avatar and badge styles? A: Define custom styles with parents CometChatAvatarStyle and CometChatBadgeStyle in themes.xml, reference them in a CometChatConversationsStyle, and apply with setStyle(). Q: How do I add custom long-press options without removing the defaults? A: Use addOptions instead of setOptions. addOptions appends your custom MenuItem objects to the existing default options.

Next steps