Skip to main content
CometChatGroups displays a searchable list of groups, acting as a container component that encapsulates and formats CometChatListBase and CometChatGroupList.

When to use this

  • You need a screen that lists all available groups for the logged-in user.
  • You want to show group names, avatars, and group type indicators (public, private, password-protected).
  • You need tap and long-press actions on group items (open group chat, mute, leave, delete).
  • You want to filter groups by joined-only status, tags, or search keywords using GroupsRequestBuilder.
  • You need real-time updates when groups are created, deleted, or membership changes occur.
  • You want to customize the group list appearance with styles, custom views, or advanced view overrides.

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 CometChatGroups XML element:
layout_activity.xml
<com.cometchat.chatuikit.groups.CometChatGroups
    android:id="@+id/groups"
    android:layout_height="match_parent"
    android:layout_width="match_parent" />
What this does: Adds the CometChatGroups component to your layout. It fills the available width and height and renders the group list for the logged-in user.
  1. Build and run your app.
  2. Verify that the group list appears with group names, avatars, and group type indicators.
  1. If you need to respond to group item taps, see the Actions subsection in Implementation.

Core concepts

  • CometChatGroups: The main component class that renders the group list. It encapsulates CometChatListBase and CometChatGroupList without introducing additional behavior.
  • Actions: Callbacks such as setOnItemClick, setOnItemLongClick, and setOnBackPressListener that let you respond to user interactions.
  • Filters: Use GroupsRequest.GroupsRequestBuilder to filter groups by limit, search keyword, joined-only status, or tags.
  • Events: Global events emitted via CometChatGroupEvents (e.g., ccGroupCreated, ccGroupDeleted) that you can listen to from anywhere in your app.
  • Style: XML theme styles (parent CometChatGroupsStyle) 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

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 CometChatGroups (e.g., cometchatGroups).
  • Applies to: CometChatGroups.
  • Default behavior: Predefined actions execute automatically (e.g., tapping a group opens the group 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 Group item is clicked, used to open a Group profile or chat screen.
YourActivity.java
cometchatGroups.setOnItemClick((view1, position, group) -> {
            
    });
What this does: Replaces the default item-click behavior. When a user taps a group, your custom lambda executes instead of the built-in navigation.

setOnItemLongClick

Function executed when a Group item is long-pressed, allowing additional actions like delete or block.
YourActivity.java
cometchatGroups.setOnItemLongClick((view1, position, group) -> {

    });
What this does: Replaces the default long-press behavior. When a user long-presses a group, 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
cometchatGroups.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
cometchatGroups.setOnSelect(t -> {

    });
What this does: Registers a callback that fires when the user selects one or more groups. The callback receives the list of selected Group objects.

setOnError

Listens for any errors that occur in the Groups component. This does not change the component’s behavior.
YourActivity.java
cometchatGroups.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
cometchatGroups.setOnLoad(list -> {

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

setOnEmpty

Called when the list is empty, enabling custom handling such as showing a placeholder message.
YourActivity.java
cometchatGroups.setOnEmpty(() -> {
            
    });
What this does: Registers a callback that fires when the group 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 groups appear in the list.
  • Where: Activity or Fragment where you hold a reference to CometChatGroups.
  • Applies to: CometChatGroups.
  • Default behavior: All groups are fetched and displayed.
  • Override: Create a GroupsRequest.GroupsRequestBuilder, configure it, and pass it to setGroupsRequestBuilder.
You can filter using the following parameters:
PropertyDescriptionCode
LimitConfigure the maximum number of groups to fetch in a single request, optimizing pagination for smoother navigation..setLimit(Int)
Search KeywordEmployed to retrieve groups that match the provided string, facilitating precise searches..setSearchKeyWord(String)
Joined OnlyExclusively fetches joined groups..joinedOnly(boolean)
TagsUtilized to fetch groups containing the specified tags..setTags(List<String>)
With TagsUtilized to retrieve groups with specific tags..withTags(boolean)
  • Code:
In the example below, the filter is applied to the Group List based on only joined groups.
GroupsRequest.GroupsRequestBuilder builder = new GroupsRequest.GroupsRequestBuilder().setLimit(10).joinedOnly(true);
cometchatGroups.setGroupsRequestBuilder(builder);
What this does: Creates a GroupsRequestBuilder that filters groups to show only joined groups with a limit of 10 per fetch. The builder is then applied to the CometChatGroups component.

SearchRequestBuilder

The SearchRequestBuilder uses GroupsRequestBuilder to filter and customize the search list based on available parameters. This keeps uniformity between the displayed Groups List and searched Group List.
GroupsRequest.GroupsRequestBuilder builder = new GroupsRequest.GroupsRequestBuilder().setLimit(10).setSearchKeyWord("**");
cometchatGroups.setSearchRequestBuilder(builder);
What this does: Creates a GroupsRequestBuilder configured for search with a limit of 10 results and a search keyword filter. The builder is applied to the search functionality of the CometChatGroups component.
  • Verify: The group list shows only joined groups (when using joinedOnly(true)) and fetches at most 10 items per request.

Events

What you’re changing: How your app reacts to global events emitted by the Groups component.
  • Where: Any Activity, Fragment, or class where you want to listen for group events.
  • Applies to: CometChatGroupEvents.
  • Default behavior: No external listeners are registered. Events are emitted but not handled outside the component.
  • Override: Add a listener using CometChatGroupEvents.addGroupListener and remove it when no longer needed using CometChatGroupEvents.removeListeners.
The list of events emitted by the Groups component is as follows:
EventsDescription
ccGroupCreated()This will get triggered when the logged in user creates a group
ccGroupDeleted()This will get triggered when the logged in user deletes a group
ccGroupLeft()This will get triggered when the logged in user leaves a group
ccGroupMemberScopeChanged()This will get triggered when the logged in user changes the scope of another group member
ccGroupMemberBanned()This will get triggered when the logged in user bans a group member from the group
ccGroupMemberKicked()This will get triggered when the logged in user kicks another group member from the group
ccGroupMemberUnbanned()This will get triggered when the logged in user unbans a user banned from the group
ccGroupMemberJoined()This will get triggered when the logged in user joins a group
ccGroupMemberAdded()This will get triggered when the logged in user add new members to the group
ccOwnershipChangedThis will get triggered when the logged in user transfer the ownership of their group to some other member
  • Code:
CometChatGroupEvents.addGroupListener("LISTENER_TAG", new CometChatGroupEvents() {
    @Override
    public void ccGroupCreated(Group group) {
        super.ccGroupCreated(group);
    }

    @Override
    public void ccGroupDeleted(Group group) {
        super.ccGroupDeleted(group);
    }

    @Override
    public void ccGroupLeft(Action actionMessage, User leftUser, Group leftGroup) {
        super.ccGroupLeft(actionMessage, leftUser, leftGroup);
    }

    @Override
    public void ccGroupMemberJoined(User joinedUser, Group joinedGroup) {
        super.ccGroupMemberJoined(joinedUser, joinedGroup);
    }

    @Override
    public void ccGroupMemberAdded(List<Action> actionMessages, List<User> usersAdded, Group userAddedIn, User addedBy) {
        super.ccGroupMemberAdded(actionMessages, usersAdded, userAddedIn, addedBy);
    }

    @Override
    public void ccGroupMemberKicked(Action actionMessage, User kickedUser, User kickedBy, Group kickedFrom) {
        super.ccGroupMemberKicked(actionMessage, kickedUser, kickedBy, kickedFrom);
    }

    @Override
    public void ccGroupMemberBanned(Action actionMessage, User bannedUser, User bannedBy, Group bannedFrom) {
        super.ccGroupMemberBanned(actionMessage, bannedUser, bannedBy, bannedFrom);
    }

    @Override
    public void ccGroupMemberUnBanned(Action actionMessage, User unbannedUser, User unBannedBy, Group unBannedFrom) {
        super.ccGroupMemberUnBanned(actionMessage, unbannedUser, unBannedBy, unBannedFrom);
    }

    @Override
    public void ccGroupMemberScopeChanged(Action actionMessage, User updatedUser, String scopeChangedTo, String scopeChangedFrom, Group group) {
        super.ccGroupMemberScopeChanged(actionMessage, updatedUser, scopeChangedTo, scopeChangedFrom, group);
    }

    @Override
    public void ccOwnershipChanged(Group group, GroupMember newOwner) {
        super.ccOwnershipChanged(group, newOwner);
    }
});
What this does: Registers a global event listener tagged with "LISTENER_TAG". When any group event fires (group created, deleted, member joined, kicked, banned, unbanned, scope changed, ownership changed), the corresponding callback executes with the relevant Group, User, and Action objects.
To remove the listener:
CometChatGroupEvents.removeListeners();
What this does: Removes all registered CometChatGroupEvents listeners, stopping your app from receiving group event callbacks.
  • Verify: Create, delete, or leave a group and confirm the corresponding event callback fires with the correct Group object.

Style

What you’re changing: The visual appearance of the Groups component using XML theme styles.
  • Where: themes.xml for style definitions, and your Activity/Fragment for applying the style.
  • Applies to: CometChatGroups.
  • Default behavior: The component uses the default CometChatGroupsStyle.
  • Override: Define a custom style with parent CometChatGroupsStyle 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="CustomGroupsStyle" parent="CometChatGroupsStyle">
        <item name="cometchatGroupsAvatar">@style/CustomAvatarStyle</item>
        <item name="cometchatGroupsSeparatorColor">#F76808</item>
        <item name="cometchatGroupsTitleTextColor">#F76808</item>
    </style>
What this does: Defines two custom styles: CustomAvatarStyle sets the avatar corner radius to 8dp and background color to #FBAA75; CustomGroupsStyle applies the avatar sub-style and sets the separator and title text colors to #F76808.
cometchatGroups.setStyle(R.style.CustomGroupsStyle);
What this does: Applies the CustomGroupsStyle theme to the CometChatGroups component, changing the avatar and separator appearance.
To know more such attributes, visit the attributes file.
  • Verify: The group list avatars display with rounded corners (8dp radius) and an orange background (#FBAA75), and separators and title text show in orange (#F76808).

Functionality

What you’re changing: Small functional customizations such as toggling visibility of UI elements and configuring selection modes.
  • Where: Activity or Fragment where you hold a reference to CometChatGroups.
  • Applies to: CometChatGroups.
  • 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 groups.setLoadingStateVisibility(View.GONE);
setErrorStateVisibilityHides the error state on fetching groups.setErrorStateVisibility(View.GONE);
setEmptyStateVisibilityHides the empty state on fetching groups.setEmptyStateVisibility(View.GONE);
setSeparatorVisibilityControls visibility of separators in the list view.setSeparatorVisibility(View.GONE);
setGroupTypeVisibilityControls visibility of the status indicator shown for the group type.setGroupTypeVisibility(View.GONE);
setSearchBoxVisibilityHides the search box shown in the toolbar.setSearchBoxVisibility(View.GONE);
setSelectionModeDetermines the selection mode for groups, enabling the user to select either a single group or multiple groups at once..setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);
setSearchkeywordFetches groups matching the passed keywords.setSearchkeyword("anything");
  • Verify: After calling a visibility method, confirm the corresponding UI element is shown or hidden. After calling setSelectionMode, confirm the selection behavior matches the mode.

Advanced views

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

setOptions

Defines the available actions when users interact with a group item, such as long-pressing or swiping. This replaces the default options entirely.
cometchatGroups.setOptions((context, group) -> Collections.emptyList());
What this does: Replaces the default long-press options with an empty list, effectively removing all long-press menu items.

addOptions

Extends the existing set of long-press actions without removing the default ones. Unlike setOptions, which replaces the default options, addOptions appends additional actions.
cometchatGroups.addOptions((context, group) -> 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.

setLoadingView

Configures a custom loading view displayed while groups are being fetched.
cometchatGroups.setLoadingView(R.layout.your_loading_view);
What this does: Replaces the default loading spinner with your custom layout resource. The custom view displays while groups are being fetched.

setEmptyView

Defines a view that appears when no groups are available.
cometchatGroups.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 group list has no items.

setErrorView

Configures the UI when an error occurs while fetching groups.
cometchatGroups.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 that appears at the start of each group item.
cometchatGroups.setLeadingView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return null;
            }

            @Override
            public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List<Group> groupList, int position) {

            }
        });
What this does: Registers a GroupsViewHolderListener that provides a custom view for the leading (left) area of each group item. createView inflates your layout, and bindView populates it with group data.
Create a custom_leading_avatar_view.xml custom layout file to inflate in setLeadingView():
custom_leading_avatar_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/leading_avatar_view"
    android:layout_width="@dimen/cometchat_40dp"
    android:layout_height="@dimen/cometchat_40dp"
    android:background="@drawable/group_leading_joined"
    android:orientation="vertical">

</LinearLayout>
What this does: Defines a custom leading view layout with a 40dp square LinearLayout that uses a drawable background to indicate group join status.
Inflate the XML and initialize the views using the group objects in setLeadingView:
cometchatGroups.setLeadingView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return LayoutInflater.from(context).inflate(R.layout.custom_leading_avatar_view, null);
            }

            @Override
            public void bindView(Context context,
                                 View createdView,
                                 Group group,
                                 RecyclerView.ViewHolder holder,
                                 List<Group> groupList,
                                 int position) {
                LinearLayout groupAvatar = createdView.findViewById(R.id.leading_avatar_view);
                groupAvatar.setBackground(group.isJoined() ? ResourcesCompat.getDrawable(getResources(),
                                                                                         R.drawable.group_leading_joined,
                                                                                         null) : ResourcesCompat.getDrawable(getResources(),
                                                                                                                             R.drawable.group_leading_join,
                                                                                                                             null));
                groupAvatar.setOnLongClickListener(v -> {
                    if (group.isJoined()) {
                        Toast.makeText(context, "Group already joined", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(context, "Joining group", Toast.LENGTH_SHORT).show();
                    }
                    return true;
                });
            }
        });
What this does: Inflates the custom leading view layout and sets the background drawable based on whether the group is joined (group_leading_joined) or not (group_leading_join). A long-click listener shows a toast indicating the group’s join status.

setTitleView

Customizes the title view of each group item, which displays the group name.
cometchatGroups.setTitleView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return null;
            }

            @Override
            public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List<Group> groupList, int position) {

            }
        });
What this does: Registers a GroupsViewHolderListener that provides a custom view for the title area of each group item. createView inflates your layout, and bindView populates it with group data.
Create a custom_title_view.xml custom layout file to inflate in setTitleView():
custom_title_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/user_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="teacher"
        android:textAppearance="?attr/cometchatTextAppearanceHeading4Medium" />

    <View
        android:id="@+id/type"
        android:layout_width="wrap_content"
        android:layout_height="15dp"
        android:layout_marginStart="@dimen/cometchat_16dp"
         />

</LinearLayout>
What this does: Defines a custom title view layout with a TextView for the group name and a View element for displaying the group type indicator icon.
Inflate the XML and initialize the views using the group objects in setTitleView:
cometchatGroups.setTitleView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return LayoutInflater.from(context).inflate(R.layout.custom_group_title_view, null);
            }

            @Override
            public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List<Group> groupList, int position) {
                LinearLayout layout = createdView.findViewById(R.id.user_layout);
                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                                                                                       ViewGroup.LayoutParams.WRAP_CONTENT);
                layout.setLayoutParams(layoutParams);
                TextView name = createdView.findViewById(R.id.title);
                name.setText(group.getName());
                View type = createdView.findViewById(R.id.role);

                if (CometChatConstants.GROUP_TYPE_PUBLIC.equals(group.getType())) {
                    type.setVisibility(View.VISIBLE);
                    type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.public_icon, null));
                } else if (CometChatConstants.GROUP_TYPE_PASSWORD.equals(group.getType())) {
                    type.setVisibility(View.VISIBLE);
                    type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.passowrd_icon, null));
                } else if (CometChatConstants.GROUP_TYPE_PRIVATE.equals(roup.getType())) {
                    type.setVisibility(View.VISIBLE);
                    type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.private_icon, null));
                } else {
                    type.setVisibility(View.GONE);
                }

            }
        });
What this does: Inflates the custom title view layout, sets the group name on the TextView, and displays a group type icon based on whether the group is public, password-protected, or private using CometChatConstants.GROUP_TYPE_PUBLIC, CometChatConstants.GROUP_TYPE_PASSWORD, and CometChatConstants.GROUP_TYPE_PRIVATE.

setTrailingView

Allows custom elements to be added at the end of each group item, such as buttons or indicators.
cometchatGroups.setTrailingView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return null;
            }

            @Override
            public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List<Group> groupList, int position) {

            }
        });
What this does: Registers a GroupsViewHolderListener that provides a custom view for the trailing (right) area of each group item. createView inflates your layout, and bindView populates it with group data.
Create a custom_tail_view.xml custom layout file to inflate in setTrailingView():
custom_tail_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <com.google.android.material.button.MaterialButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:backgroundTint="#EDEAFA"
        android:text="+ joined"
        android:textStyle="bold"
        android:textAppearance="?attr/cometchatTextAppearanceCaption2Regular"
        android:textAllCaps="true"
        android:textColor="#6852D6"
        app:cornerRadius="@dimen/cometchat_1000dp" />
</LinearLayout>
What this does: Defines a custom trailing view layout with a MaterialButton styled as a purple “joined” badge with rounded corners.
Inflate the XML and initialize the views using the group objects in setTrailingView:
cometchatGroups.setTrailingView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null);
            }

            @Override
            public void bindView(Context context,
                                 View createdView,
                                 Group group,
                                 RecyclerView.ViewHolder holder,
                                 List<Group> groupList,
                                 int position) {
                 MaterialButton button = createdView.findViewById(R.id.button);
                button.setText(group.isJoined() ? "Joined" : "+ Join");
            }
        });
What this does: Inflates the custom trailing view layout and sets the button text to “Joined” if the user has joined the group, or ”+ Join” if the user has not joined.

setItemView

Assigns a fully custom ListItem layout to the Groups component, replacing the default design.
cometchatGroups.setItemView(new GroupsViewHolderListener() {
    @Override
    public View createView(Context context, CometchatListBaseItemsBinding cometChatListItem) {
        return null;
    }

    @Override
    public void bindView(Context context, View view, Group group, RecyclerView.ViewHolder viewHolder, List<Group> list, int i) {

    }
});
What this does: Registers a GroupsViewHolderListener that replaces the entire default group list item layout. createView inflates your custom layout, and bindView populates it with group data.
Create a custom_group_list_itemd.xml custom layout file to inflate in setItemView():
custom_group_list_itemd.xml

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

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

        <TextView
            android:id="@+id/tvName"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:maxLines="1"
            android:textAppearance="?attr/cometchatTextAppearanceHeading4Bold"
            android:textColor="?attr/cometchatTextColorPrimary" />

        <com.google.android.material.card.MaterialCardView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cometchat_16dp"
            android:layout_marginTop="@dimen/cometchat_2dp"
            android:layout_marginBottom="@dimen/cometchat_2dp"
            android:elevation="0dp"
            app:cardBackgroundColor="#EDEAFA"
            app:cardCornerRadius="@dimen/cometchat_radius_max"
            app:cardElevation="0dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/cometchat_margin_3"
                android:layout_marginTop="@dimen/cometchat_margin_1"
                android:layout_marginEnd="@dimen/cometchat_margin_3"
                android:layout_marginBottom="@dimen/cometchat_margin_1"
                android:text="JOIN"
                android:textAppearance="@style/CometChatTextAppearanceCaption1.Medium"
                android:textColor="?attr/cometchatPrimaryColor" />
        </com.google.android.material.card.MaterialCardView>
    </LinearLayout>

    <TextView
        android:id="@+id/tvSubtitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/cometchat_margin_1"
        android:textAppearance="?attr/cometchatTextAppearanceBodyRegular"
        android:textColor="?attr/cometchatTextColorSecondary" />
</LinearLayout>
What this does: Defines a custom list item layout with a group name TextView, a “JOIN” badge in a MaterialCardView, and a subtitle TextView for displaying member count and description.
Inflate the XML and initialize the views using the group objects in setItemView:
YourActivity.java
cometChatGroup.setItemView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return View.inflate(context,R.layout.custom_group_list_item,null);
            }

            @Override
            public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List<Group> groupList, int position) {
                TextView groupName = createdView.findViewById(R.id.tvName);
                TextView groupMemberCount = createdView.findViewById(R.id.tvSubtitle);
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                createdView.setLayoutParams(params);
                groupName.setText(group.getName());
                groupMemberCount.setText(group.getMembersCount() > 1 ? group.getMembersCount() + " members" : group.getMembersCount() + " member" + " • " + group.getDescription());
            }
        });
What this does: Inflates the custom list item layout and populates it with the group name and a subtitle showing the member count (e.g., “5 members”) and group description. If the group has one member, it shows “1 member” followed by the description.

setSubTitleView

Customizes the subtitle view for each group item, which displays extra information below the group name.
CometChatGroup.setSubtitleView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return null;
            }

            @Override
            public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List<Group> groupList, int position) {

            }
        });
What this does: Registers a GroupsViewHolderListener that provides a custom view for the subtitle area of each group item. createView inflates your layout, and bindView populates it with group data.
Inflate the XML and initialize the views using the group objects in setSubTitleView:
YourActivity.java
cometChatGroup.setSubtitleView(new GroupsViewHolderListener() {
            @Override
            public View createView(Context context, CometchatListBaseItemsBinding listItem) {
                return new TextView(context);
            }

            @Override
            public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List<Group> groupList, int position) {
                TextView textView = (TextView) createdView;
                textView.setText(group.getMembersCount() > 1 ? group.getMembersCount() + " members" : group.getMembersCount() + " member" + " • " + group.getDescription());

            }
        });
What this does: Replaces the default subtitle with a custom TextView that shows the member count (e.g., “5 members”) and group description. If the group has one member, it shows “1 member” followed by the description.

setOverflowMenu

Customizes the overflow menu (three-dot ⋮ icon) with additional options.
cometchatGroups.setOverflowMenu(View v);
What this does: Sets a custom View as the overflow menu in the groups toolbar. Pass any view (e.g., an icon button) to replace the default overflow menu.
Create an overflow_menu_layout.xml custom view file to inflate and pass to setOverflowMenu:
overflow_menu_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/ivMenu"
        android:layout_width="@dimen/cometchat_24dp"
        android:layout_height="@dimen/cometchat_24dp"
        android:layout_marginStart="@dimen/cometchat_margin_4"
        android:importantForAccessibility="no"
        android:src="@drawable/ic_create_group" />

</LinearLayout>
What this does: Defines a custom overflow menu layout with a 24dp ImageView using a “create group” icon drawable.
Inflate the view and pass it to setOverflowMenu. Get child view references to handle click actions:
YourActivity.java
View view = getLayoutInflater().inflate(R.layout.overflow_menu_layout, null);
ImageView imgRefresh = view.findViewById(R.id.ivMenu);
imgRefresh.setOnClickListener(v -> {
    Toast.makeText(requireContext(), "Clicked on Refresh", Toast.LENGTH_SHORT).show();
});
cometchatGroups.setOverflowMenu(view);
What this does: Inflates the custom overflow menu layout, sets a click listener on the ImageView that shows a “Clicked on Refresh” toast, and passes the view to setOverflowMenu to replace the default overflow menu.
  • Verify: After setting any advanced view, confirm the custom view renders in the correct position within the group list item, and the data binding populates correctly for each group.

Customization matrix

What you want to changeWhereProperty/APIExample
Avatar style (corner radius, background)themes.xmlCometChatGroupsStyle with cometchatGroupsAvatar<item name="cometchatAvatarStrokeRadius">8dp</item>
Separator colorthemes.xmlCometChatGroupsStyle with cometchatGroupsSeparatorColor<item name="cometchatGroupsSeparatorColor">#F76808</item>
Title text colorthemes.xmlCometChatGroupsStyle with cometchatGroupsTitleTextColor<item name="cometchatGroupsTitleTextColor">#F76808</item>
Apply a custom styleActivity/FragmentsetStyle(int styleRes)cometchatGroups.setStyle(R.style.CustomGroupsStyle);
Back button visibilityActivity/FragmentsetBackIconVisibility(int).setBackIconVisibility(View.VISIBLE);
Toolbar visibilityActivity/FragmentsetToolbarVisibility(int).setToolbarVisibility(View.GONE);
Loading state visibilityActivity/FragmentsetLoadingStateVisibility(int).setLoadingStateVisibility(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);
Group type indicator visibilityActivity/FragmentsetGroupTypeVisibility(int).setGroupTypeVisibility(View.GONE);
Search box visibilityActivity/FragmentsetSearchBoxVisibility(int).setSearchBoxVisibility(View.GONE);
Selection mode (single/multiple)Activity/FragmentsetSelectionMode(SelectionMode).setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);
Search keyword filterActivity/FragmentsetSearchkeyword(String).setSearchkeyword("anything");
Filter groups (joined only, limit, tags)Activity/FragmentsetGroupsRequestBuilder(GroupsRequestBuilder)See Filters code above
Search request builderActivity/FragmentsetSearchRequestBuilder(GroupsRequestBuilder)See SearchRequestBuilder code above
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)cometchatGroups.setLoadingView(R.layout.your_loading_view);
Empty viewActivity/FragmentsetEmptyView(int)cometchatGroups.setEmptyView(R.layout.your_empty_view);
Error viewActivity/FragmentsetErrorView(int)cometchatGroups.setErrorView(R.layout.your_empty_view);
Leading view (avatar area)Activity/FragmentsetLeadingView(GroupsViewHolderListener)See setLeadingView code above
Title viewActivity/FragmentsetTitleView(GroupsViewHolderListener)See setTitleView code above
Trailing viewActivity/FragmentsetTrailingView(GroupsViewHolderListener)See setTrailingView code above
Entire list itemActivity/FragmentsetItemView(GroupsViewHolderListener)See setItemView code above
Subtitle viewActivity/FragmentsetSubTitleView(GroupsViewHolderListener)See setSubTitleView code above
Overflow menuActivity/FragmentsetOverflowMenu(View)cometchatGroups.setOverflowMenu(View v);

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.
Group list is empty despite having groupsVerify that a user is logged in with CometChatUIKit.login() before displaying the component. The component fetches groups for the logged-in user only.
Only joined groups appearIf you set joinedOnly(true) on the GroupsRequestBuilder, only groups the user has joined are shown. Remove joinedOnly(true) to show all groups.
Filters not appliedEnsure you call setGroupsRequestBuilder(builder) on the CometChatGroups instance after creating and configuring the builder.
Custom style not visibleVerify the style parent is CometChatGroupsStyle 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 CometChatGroupEvents.addGroupListener with a unique tag. If you use the same tag as another listener, the previous one is replaced.
Group type indicator not showingIf you called setGroupTypeVisibility(View.GONE), the group type indicator is hidden. Call setGroupTypeVisibility(View.VISIBLE) to restore it.
Custom view returns null in createViewIf createView returns null, the default view is used. Return a valid inflated View to replace the default.
Search not workingIf you set a SearchRequestBuilder with setSearchRequestBuilder, ensure the builder is configured with setSearchKeyWord. If the search keyword is empty, all groups are returned.

FAQ

Q: How do I show only joined groups? A: Create a GroupsRequest.GroupsRequestBuilder, call joinedOnly(true), and pass it to setGroupsRequestBuilder. Q: How do I listen for group creation or deletion events outside the component? A: Use CometChatGroupEvents.addGroupListener("YOUR_TAG", ...) and override ccGroupCreated or ccGroupDeleted. Call CometChatGroupEvents.removeListeners() to unsubscribe. Q: How do I customize the avatar and separator styles? A: Define custom styles with parents CometChatAvatarStyle and CometChatGroupsStyle in themes.xml, reference the avatar style in cometchatGroupsAvatar, 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. Q: How do I replace the entire group list item layout? A: Use setItemView with a GroupsViewHolderListener. Inflate your custom layout in createView and populate it with group data in bindView.

Next steps