Conversations
Overview
The Conversations is a Component, That shows all conversations related to the currently logged-in user,

Usage
Integration
There are multiple ways in which you can use Conversations in your app. Layout File: To use Conversations in your `layout_activity.xml, use the following code snippet.
<com.cometchat.chatuikit.conversations.CometChatConversations
android:id="@+id/conversation"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- Activity: To use Conversations in your Activity, use the following code snippet.
- Java
- Kotlin
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new CometChatConversations(this));
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(CometChatConversations(this))
}
- Fragment: To use
Conversations
in yourFragment
, use the following code snippet.
- Java
- Kotlin
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return new CometChatConversations(getContext());
}
override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View {
return CometChatConversations(requireContext())
}
Actions
Actions dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs.
setOnItemClick
Function invoked when a conversation item is clicked, typically used to open a detailed chat screen.
- Java
- Kotlin
cometchatConversations.setOnItemClick((view1, position, conversation) -> {
});
cometchatConversations.onItemClick = OnItemClick { view, position, conversation ->
}
setOnItemLongClick
Function executed when a conversation item is long-pressed, allowing additional actions like delete or select.
- Java
- Kotlin
cometchatConversations.setOnItemLongClick((view1, position, conversation) -> {
});
cometchatConversations.onItemLongClick = OnItemLongClick({ view, position, conversation ->
})
setOnBackPressListener
OnBackPressListener
is triggered when you press the back button in the app bar. It has a predefined behavior; when clicked, it navigates to the previous activity. However, you can override this action using the following code snippet.
- Java
- Kotlin
cometchatConversations.setOnBackPressListener(() -> {
});
cometchatConversations.onBackPressListener = OnBackPress {
}
setOnSelect
Called when a item from the fetched list is selected, useful for multi-selection features.
- Java
- Kotlin
cometchatConversations.setOnSelect(t -> {
});
cometchatConversations.setOnSelect(object : OnSelection<Conversation?> {
override fun onSelection(t: MutableList<Conversation?>?) {
}
})
OnError
This action doesn't change the behavior of the component but rather listens for any errors that occur in the Conversations component.
- Java
- Kotlin
cometchatConversations.setOnError(cometchatException -> {
});
cometchatConversations.setOnError {
}
setOnLoad
Invoked when the list is successfully fetched and loaded, helping track component readiness.
- Java
- Kotlin
cometchatConversations.setOnLoad(list -> {
});
cometchatConversations.setOnLoad(object : OnLoad<Conversation?> {
override fun onLoad(list: MutableList<Conversation?>?) {
}
})
setOnEmpty
Called when the list is empty, enabling custom handling such as showing a placeholder message.
- Java
- Kotlin
cometchatConversations.setOnEmpty(() -> {
});
cometchatConversations.setOnEmpty{
}
Filters
You can set ConversationsRequestBuilder
in the Conversations Component to filter the conversation list. You can modify the builder as per your specific requirements with multiple options available to know more refer to ConversationRequestBuilder.
You can set filters using the following parameters.
- Conversation Type: Filters on type of Conversation,
User
orGroups
- Limit: Number of conversations fetched in a single request.
- WithTags: Filter on fetching conversations containing tags
- Tags: Filters on specific
Tag
- UserTags: Filters on specific User
Tag
- GroupTags: Filters on specific Group
Tag
- Java
- Kotlin
ConversationsRequest.ConversationsRequestBuilder builder = new ConversationsRequest.ConversationsRequestBuilder();
builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER);
builder.setLimit(50);
cometChatConversations.setConversationsRequestBuilder(builder);
val builder = ConversationsRequest.ConversationsRequestBuilder()
builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER)
builder.setLimit(50)
cometChatConversations.setConversationsRequestBuilder(builder)
Events
Events are emitted by a Component
. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed.
1. ConversationDeleted
This event will be emitted when the user deletes a conversation
- Java
- Kotlin
CometChatConversationEvents.addListener("YOUR_LISTENER_TAG", new CometChatConversationEvents() {
@Override
public void ccConversationDeleted(Conversation conversation) {
super.ccConversationDeleted(conversation);
}
});
CometChatConversationEvents.removeListener("YOUR_LISTENER_TAG");
CometChatConversationEvents.addListener("LISTENER_TAG", object : CometChatConversationEvents() {
override fun ccConversationDeleted(conversation: Conversation) {
super.ccConversationDeleted(conversation)
}
})
CometChatConversationEvents.removeListener("LISTENER_TAG");
Customization
To fit your app's design requirements, you can customize the appearance of the conversation component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs.
Style
Using Style you can customize the look and feel of the component in your app, These parameters typically control elements such as the color, size, shape, and fonts used within the component.
setStyle
You can set the styling object to the CometChatConversations
Component to customize the styling.

<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>
- Java
- Kotlin
cometChatConversations.setStyle(R.style.CustomConversationsStyle);
cometChatConversations.setStyle(R.style.CustomConversationsStyle)
To know more such attributes, visit the attributes file.
Functionality
These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements.
Below is a list of customizations along with corresponding code snippets
Methods | Description | Code |
---|---|---|
setBackIconVisibility | Used to toggle visibility for back button in the app bar | .setBackIconVisibility(View.VISIBLE); |
setToolbarVisibility | Used to toggle visibility for back button in the app bar | .setToolbarVisibility(View.GONE); |
setLoadingStateVisibility | Used to hide loading state while fetching Users | .setLoadingStateVisibility(View.GONE); |
setDeleteConversationOptionVisibility | Used to toggle visibility for delete option on a long press of conversation item | .setDeleteConversationOptionVisibility(View.GONE); |
setErrorStateVisibility | Used to hide error state on fetching conversations | .setErrorStateVisibility(View.GONE); |
setEmptyStateVisibility | Used to hide empty state on fetching conversations | .setEmptyStateVisibility(View.GONE); |
setSeparatorVisibility | Used to control visibility of Separators in the list view | .setSeparatorVisibility(View.GONE); |
setUsersStatusVisibility | Used to control visibility of status indicator shown if user is online | .setUsersStatusVisibility(View.GONE); |
setGroupTypeVisibility | Used to control visibility of status indicator shown for the group type | .setGroupTypeVisibility(View.GONE); |
setReceiptsVisibility | Used to hide receipts shown in the subtitle of the conversation item without disabling the functionality of marking messages as read and delivered. | .setReceiptsVisibility(View.GONE); |
setSelectionMode | This method determines the selection mode for conversations, enabling users to select either a single conversation or multiple conversations at once. | .setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE); |
Advanced
For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component.
setOptions
This method sets a predefined list of actions that users can perform when they long press a conversation in the list. These options typically include:
- Deleting a conversation
- Marking a conversation as read or unread
- Pinning or unpinning a conversation
- Muting notifications for a specific conversation
By customizing these options, developers can provide a streamlined and contextually relevant user experience.
- Java
- Kotlin
cometchatConversations.setOptions((context, conversation) -> Collections.emptyList());
cometchatConversations.options = Function2<Context?, Conversation?, List<CometChatPopupMenu.MenuItem?>?> { context, conversation -> emptyList<CometChatPopupMenu.MenuItem?>() }
Demonstration

- Java
- Kotlin
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;
});
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
}
addOptions
This method extends the existing set of actions available when users long press a conversation item. Unlike setOptionsDefines, which replaces the default options, addOptionsAdds allows developers to append additional actions without removing the default ones. Example use cases include:
- Adding a "Report Spam" action
- Introducing a "Save to Notes" option
- Integrating third-party actions such as "Share to Cloud Storage"
This method provides flexibility in modifying user interaction capabilities.
- Java
- Kotlin
cometchatConversations.addOptions((context, conversation) -> Collections.emptyList());
cometchatConversations.addOptions { context, conversation -> emptyList<CometChatPopupMenu.MenuItem?>() }
Demonstration

- Java
- Kotlin
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;
});
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, "Delete", 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, "Archive", 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
}
disableSoundForMessages
This method disables sound notifications for incoming messages. When activated, the application will not play an audio alert when new messages arrive. This feature is beneficial in scenarios where:
- Users prefer a silent messaging experience
- The app is being used in a professional or quiet environment
- Background processes need to minimize distractions
By providing this option, the app allows users to tailor their notification preferences.
- Java
- Kotlin
cometchatConversations.disableSoundForMessages(true);
cometchatConversations.disableSoundForMessages(true)
setCustomSoundForMessages
This method enables users to personalize their chat experience by setting a custom sound file for incoming message notifications. Users can choose from:
- Default system sounds
- Custom sound files uploaded by the user
- Theme-based or brand-specific notification sounds
By allowing sound customization, this feature enhances personalization and improves user engagement.
- Java
- Kotlin
cometchatConversations.setCustomSoundForMessages(com.cometchat.chatuikit.R.raw.cometchat_beep2);
cometchatConversations.setCustomSoundForMessages(com.cometchat.chatuikit.R.raw.cometchat_beep2)
setLoadingView
This method allows developers to set a custom loading view that is displayed when data is being fetched or loaded within the component. Instead of using a default loading spinner, a custom animation, progress bar, or branded loading screen can be displayed.
Use cases:
- Showing a skeleton loader for conversations while data loads
- Displaying a custom progress indicator with branding
- Providing an animated loading experience for a more engaging UI
- Java
- Kotlin
cometchatConversations.setLoadingView(R.layout.your_loading_view);
cometchatConversations.loadingView = R.layout.your_loading_view
setEmptyView
Configures a custom view to be displayed when there are no conversations or messages in the list. This improves the user experience by providing meaningful content instead of an empty screen.
Examples:
- Displaying a message like "No conversations yet. Start a new chat!"
- Showing an illustration or animation to make the UI visually appealing
- Providing a button to start a new conversation
- Java
- Kotlin
cometchatConversations.setEmptyView(R.layout.your_empty_view);
cometchatConversations.emptyView = R.layout.your_empty_view
setErrorView
Defines a custom error state view that appears when an issue occurs while loading conversations or messages. This enhances the user experience by displaying friendly error messages instead of generic system errors.
Common use cases:
- Showing "Something went wrong. Please try again." with a retry button
- Displaying a connection issue message if the user is offline
- Providing troubleshooting steps for the error
- Java
- Kotlin
cometchatConversations.setErrorView(R.layout.your_empty_view);
cometchatConversations.errorView = R.layout.your_error_view
setLeadingView
Allows setting a custom leading view element that appears at the beginning of each conversation item. This is typically used to modify profile pictures, avatars, or icons in the conversation list.
Examples:
- Displaying user avatars with online/offline status indicators
- Using initials or custom graphics instead of images
- Java
- Kotlin
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) {
}
});
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
) {
}
})
Demonstration

<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>
You can create an leading_view.xml
as a custom layout file. Which we will 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>
In the method setLeadingView
you need to inflate the XML and initialize the views using the conversation objects.
- Java
- Kotlin
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);
}
}
}
});
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
}
}
}
})
setTitleView
Overrides the default title view in the conversation list with a custom layout. This is useful for branding or modifying how conversation names and details are displayed.
Examples:
- Displaying conversation titles with additional metadata (e.g., last seen time)
- Custom fonts or text styles for conversation names
- Adding icons or indicators next to titles
- Java
- Kotlin
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) {
}
});
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
) {
}
})
Demonstration

You can create an custom_title_view.xml
as a custom layout file. Which we will 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>
In the method setTitleView
you need to inflate the XML and initialize the views using the conversation objects.
- Java
- Kotlin
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);
}
}
});
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
}
}
})
setTrailingView
Customizes the trailing (end) view of a conversation item, which is typically used for action buttons or additional information.
Examples:
- Adding a mute/unmute button for each conversation
- Displaying the last message time in a custom format
- Showing unread message counts or notification badges
You can create an custom_tail_view.xml
as a custom layout file. Which we will 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>
In the method setTrailingView
you need to inflate the XML and initialize the views using the conversation objects.
- Java
- Kotlin
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));
}
}
});
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) {
// Convert seconds to milliseconds
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)
// Check if the timestamp is within the last hour
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"))
return
} 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"))
return
}
// Check if the timestamp is within the last 24 hours
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))
}
}
})
Demonstration

- Java
- Kotlin
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) {
}
});
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
) {
}
})
setItemView
This function allows developers to assign a completely custom list item design to the Conversations Component, replacing the default layout.
Use cases:
- Implementing a unique conversation list design with custom styling
- Adding extra elements like swipe gestures, priority indicators, or group labels
- Fully customizing how messages are displayed in the list
- Java
- Kotlin
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) {
}
});
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
) {
}
})
Demonstration

You can create an item_converation_list.xml
as a custom layout file. Which we will 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>
In the method setItemView
you need to inflate the XML and initialize the views using the conversation objects.
- Java
- Kotlin
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);
}
});
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
}
})
setTextFormatters
This method enables developers to define and apply text formatters that dynamically modify or transform message content before rendering it in the UI. Text formatters can be used for purposes such as:
- Automatically converting URLs into clickable links
- Applying Markdown or rich text styling
- Replacing certain words or patterns with emojis or predefined text
- Censoring specific words for moderation
By utilizing this method, developers can enhance readability, usability, and compliance with content guidelines. MentionsFormatter Guide
Example

<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>
- Java
- Kotlin
// 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);
// Initialize CometChatMentionsFormatter
val mentionFormatter = 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.
val textFormatters: MutableList<CometChatTextFormatter> = ArrayList()
textFormatters.add(mentionFormatter)
cometChatConversations.setTextFormatters(textFormatters)
setOverflowMenu
The setOverflowMenu method allows developers to customize the overflow menu within the Conversations component. This menu typically appears as a three-dot (⋮) or hamburger icon and provides users with additional options beyond those displayed in the main UI.
Use Cases:
- Archive Chat
- Mark All as Read
- Delete Conversations
- Java
- Kotlin
cometChatConversations.setOverflowMenu(View v);
cometChatConversations.setOverflowMenu(v)
Demonstration

You can create a view_menu.xml
as a custom view file. Which we will inflate and pass it to .setMenu
.
<?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>
You inflate the view and pass it to setMenu
. You can get the child view reference and can handle click actions.
- Java
- Kotlin
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);
}
}
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.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
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(
CometChatUIKit.getLoggedInUser().name,
CometChatUIKit.getLoggedInUser().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 { v: View? ->
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 { view ->
popupWindow.dismiss()
}
popupMenuBinding.tvUserName.setOnClickListener { view ->
popupWindow.dismiss()
}
popupMenuBinding.tvLogout.setOnClickListener { view ->
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
val offsetY = 0
popupWindow.showAsDropDown(anchorView, offsetX, offsetY)
}
}
setDateFormat
This method customizes the date format used for displaying timestamps in conversations or chat components. Developers can specify formats such as:
- dd/MM/yyyy HH:mm → Example: 10/07/2024 14:30
- MMM dd, yyyy → Example: Jul 10, 2024
- hh:mm a → Example: 02:30 PM
Custom date patterns improve the localization and readability of time-sensitive messages, catering to different regional preferences.
- Java
- Kotlin
cometChatConversations.setDateFormat(SimpleDateFormat)
cometChatConversations.setDateFormat(SimpleDateFormat)
Demonstration

- Java
- Kotlin
cometchatConversations.setDatePattern(new SimpleDateFormat("dd Mmm, hh:mm a",Locale.getDefault()));
cometchatConversations.setDatePattern(SimpleDateFormat("dd MMM, hh:mm a",Locale.getDefault()))
setSubtitleView
The setSubtitleView method allows developers to customize the subtitle view of each conversation item in the list. The subtitle typically displays additional information below the conversation title, such as the last message, message status, or other relevant details.
Use Cases:
- Customizing the Last Message Display – Modify how the last message appears, including text styling, truncation, or emoji support.
- Message Status Indicators – Show message status (e.g., Sent, Delivered, Read) alongside the last message.
- Typing Indicators – Display "User is typing..." in real time.
- Java
- Kotlin
cometChatConversations.setSubtitleView()
cometChatConversations.setSubtitleView()
Demonstration

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