> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-rn-guide-message-privately.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Users

> Scrollable list of all available users with search, avatars, names, and online/offline status indicators.

<Accordion title="AI Integration Quick Reference">
  ```json theme={null}
  {
    "component": "CometChatUsers",
    "package": "com.cometchat.chatuikit.users",
    "xmlElement": "<com.cometchat.chatuikit.users.CometChatUsers />",
    "description": "Scrollable list of all available users with search, avatars, names, and online/offline status indicators.",
    "primaryOutput": {
      "method": "setOnItemClick",
      "type": "OnItemClick<User>"
    },
    "methods": {
      "data": {
        "setUsersRequestBuilder": {
          "type": "UsersRequest.UsersRequestBuilder",
          "default": "SDK default",
          "note": "Pass the builder, not the result of .build()"
        },
        "setSearchRequestBuilder": {
          "type": "UsersRequest.UsersRequestBuilder",
          "default": "Same as main builder",
          "note": "Separate builder for search results"
        }
      },
      "callbacks": {
        "setOnItemClick": "OnItemClick<User>",
        "setOnItemLongClick": "OnItemLongClick<User>",
        "setOnBackPressListener": "OnBackPress",
        "setOnSelect": "OnSelection<User>",
        "setOnError": "OnError",
        "setOnLoad": "OnLoad<User>",
        "setOnEmpty": "OnEmpty"
      },
      "visibility": {
        "setBackIconVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.GONE" },
        "setToolbarVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setLoadingStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setErrorStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setEmptyStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setSeparatorVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setUserStatusVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setStickyHeaderVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setSearchBoxVisibility": { "type": "int", "default": "View.VISIBLE" }
      },
      "selection": {
        "setSelectionMode": {
          "type": "UIKitConstants.SelectionMode",
          "values": ["NONE", "SINGLE", "MULTIPLE"],
          "default": "NONE"
        }
      },
      "viewSlots": {
        "seItemView": "UsersViewHolderListener — entire list item row (note: typo in SDK method name)",
        "setLeadingView": "UsersViewHolderListener — avatar / left section",
        "setTitleView": "UsersViewHolderListener — name / title text",
        "setSubtitleView": "UsersViewHolderListener — subtitle text below name",
        "setTrailingView": "UsersViewHolderListener — right section",
        "setLoadingView": "@LayoutRes int — loading spinner",
        "setEmptyView": "@LayoutRes int — empty state",
        "setErrorView": "@LayoutRes int — error state",
        "setOverflowMenu": "View — toolbar menu",
        "setOptions": "Function2<Context, User, List<MenuItem>> — long-press context menu (replaces defaults)",
        "addOptions": "Function2<Context, User, List<MenuItem>> — long-press context menu (appends to defaults)"
      },
      "advanced": {
        "selectUser": "User, SelectionMode — programmatic selection",
        "clearSelection": "void — clears all selected users",
        "getSelectedUsers": "List<User> — returns selected items",
        "setSearchKeyword": "String — programmatic search",
        "setTitleText": "String — custom toolbar title",
        "setSearchPlaceholderText": "String — search placeholder",
        "getBinding": "CometchatUserListBinding — root ViewBinding",
        "getViewModel": "UsersViewModel — internal ViewModel access",
        "getUsersAdapter": "UsersAdapter — internal adapter access",
        "setAdapter": "UsersAdapter — replace the default adapter"
      },
      "style": {
        "setStyle": {
          "type": "@StyleRes int",
          "parent": "CometChatUsersStyle"
        }
      }
    },
    "events": [
      {
        "name": "CometChatUserEvents.ccUserBlocked",
        "payload": "User",
        "description": "Logged-in user blocked another user"
      },
      {
        "name": "CometChatUserEvents.ccUserUnblocked",
        "payload": "User",
        "description": "Logged-in user unblocked another user"
      }
    ],
    "sdkListeners": [
      "onUserOnline",
      "onUserOffline"
    ]
  }
  ```
</Accordion>

## Where It Fits

`CometChatUsers` is a list component. It renders all available users and emits the selected `User` via `setOnItemClick`. Wire it to `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` to build a direct messaging layout.

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

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

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

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

            users.setOnItemClick { view, position, user ->
                messageHeader.setUser(user)
                messageList.setUser(user)
                messageComposer.setUser(user)
            }
        }
    }
    ```
  </Tab>

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

        private CometChatUsers users;
        private CometChatMessageHeader messageHeader;
        private CometChatMessageList messageList;
        private CometChatMessageComposer messageComposer;

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

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

            users.setOnItemClick((view, position, user) -> {
                messageHeader.setUser(user);
                messageList.setUser(user);
                messageComposer.setUser(user);
            });
        }
    }
    ```
  </Tab>
</Tabs>

## Quick Start

Add the component to your layout XML:

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

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/PaxBG9I1yMoeQmt2/images/358a0b21-users-4e1d9c895a8ae47d23ac0d6646db160b.png?fit=max&auto=format&n=PaxBG9I1yMoeQmt2&q=85&s=883ebbcc6e353ebf259c124b36875272" width="2560" height="1600" data-path="images/358a0b21-users-4e1d9c895a8ae47d23ac0d6646db160b.png" />
</Frame>

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

To add programmatically in an Activity:

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

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

Or in a Fragment:

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

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

## Filtering Users

Pass a `UsersRequest.UsersRequestBuilder` to `setUsersRequestBuilder`. Pass the builder instance — not the result of `.build()`.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = UsersRequest.UsersRequestBuilder()
        .friendsOnly(false)
        .setLimit(10)
    cometChatUsers.setUsersRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    UsersRequest.UsersRequestBuilder builder = new UsersRequest.UsersRequestBuilder()
        .friendsOnly(false)
        .setLimit(10);
    cometChatUsers.setUsersRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

### Filter Recipes

| Recipe               | Code                                                           |
| -------------------- | -------------------------------------------------------------- |
| Friends only         | `builder.friendsOnly(true)`                                    |
| Limit to 10 per page | `builder.setLimit(10)`                                         |
| Search by keyword    | `builder.setSearchKeyword("john")`                             |
| Hide blocked users   | `builder.hideBlockedUsers(true)`                               |
| Filter by roles      | `builder.setRoles(Arrays.asList("admin", "moderator"))`        |
| Filter by tags       | `builder.setTags(Arrays.asList("vip"))`                        |
| Online users only    | `builder.setUserStatus(CometChatConstants.USER_STATUS_ONLINE)` |
| Filter by UIDs       | `builder.setUIDs(Arrays.asList("uid1", "uid2"))`               |

> The component uses infinite scroll — the next page loads as the user scrolls to the bottom. Refer to [UsersRequestBuilder](/sdk/android/retrieve-users) for the full builder API.

### Search Request Builder

Use `setSearchRequestBuilder` to customize the search list separately from the main list:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val searchBuilder = UsersRequest.UsersRequestBuilder()
        .setSearchKeyword("**")
    cometChatUsers.setSearchRequestBuilder(searchBuilder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    UsersRequest.UsersRequestBuilder searchBuilder = new UsersRequest.UsersRequestBuilder()
        .setSearchKeyword("**");
    cometChatUsers.setSearchRequestBuilder(searchBuilder);
    ```
  </Tab>
</Tabs>

## Actions and Events

### Callback Methods

#### `setOnItemClick`

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

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

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

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

#### `setOnItemLongClick`

Fires when a user row is long-pressed. Use for additional actions like block or mute.

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

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

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

#### `setOnBackPressListener`

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

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

    }
    ```
  </Tab>

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

#### `setOnSelect`

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

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

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

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

#### `setOnError`

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

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

    }
    ```
  </Tab>

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

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

#### `setOnLoad`

Fires when the list is successfully fetched and loaded.

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

        }
    })
    ```
  </Tab>

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

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

#### `setOnEmpty`

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

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

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

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

### Global UI Events

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

| Event             | Fires when                               | Payload |
| ----------------- | ---------------------------------------- | ------- |
| `ccUserBlocked`   | The logged-in user blocks another user   | `User`  |
| `ccUserUnblocked` | The logged-in user unblocks another user | `User`  |

<Tabs>
  <Tab title="Kotlin">
    ```kotlin Add Listener lines theme={null}
    CometChatUserEvents.addUserListener("LISTENER_TAG", object : CometChatUserEvents() {
        override fun ccUserBlocked(user: User?) {
            super.ccUserBlocked(user)
        }

        override fun ccUserUnblocked(user: User?) {
            super.ccUserUnblocked(user)
        }
    })
    ```

    Remove Listener

    ```
    CometChatUserEvents.removeListener("LISTENER_TAG")
    ```
  </Tab>

  <Tab title="Java">
    ```java Add Listener lines theme={null}
    CometChatUserEvents.addUserListener("LISTENER_TAG", new CometChatUserEvents() {
        @Override
        public void ccUserBlocked(User user) {
            super.ccUserBlocked(user);
        }

        @Override
        public void ccUserUnblocked(User user) {
            super.ccUserUnblocked(user);
        }
    });
    ```

    Remove Listener

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

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

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

| SDK Listener    | Internal behavior                             |
| --------------- | --------------------------------------------- |
| `onUserOnline`  | Updates online status indicator for the user  |
| `onUserOffline` | Updates offline status indicator for the user |

> Automatic: user presence changes update the status indicator in real time.

## Functionality

Small functional customizations such as toggling visibility of UI elements and configuring selection modes.

| Methods                     | Description                                               | Code                                                        |
| --------------------------- | --------------------------------------------------------- | ----------------------------------------------------------- |
| `setBackIconVisibility`     | Toggles visibility for the back button in the app bar     | `.setBackIconVisibility(View.VISIBLE);`                     |
| `setToolbarVisibility`      | Toggles visibility for the toolbar in the app bar         | `.setToolbarVisibility(View.GONE);`                         |
| `setStickyHeaderVisibility` | Toggles visibility for the alphabetical sticky header     | `.setStickyHeaderVisibility(View.GONE);`                    |
| `setLoadingStateVisibility` | Hides the loading state while fetching users              | `.setLoadingStateVisibility(View.GONE);`                    |
| `setErrorStateVisibility`   | Hides the error state on fetching users                   | `.setErrorStateVisibility(View.GONE);`                      |
| `setEmptyStateVisibility`   | Hides the empty state on fetching users                   | `.setEmptyStateVisibility(View.GONE);`                      |
| `setSeparatorVisibility`    | Controls visibility of separators in the list view        | `.setSeparatorVisibility(View.GONE);`                       |
| `setUserStatusVisibility`   | Controls visibility of the online status indicator        | `.setUserStatusVisibility(View.GONE);`                      |
| `setSearchBoxVisibility`    | Controls visibility of the search box in the toolbar      | `.setSearchBoxVisibility(View.GONE);`                       |
| `setSelectionMode`          | Determines the selection mode (single or multiple)        | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` |
| `setSearchKeyword`          | Programmatically triggers a search with the given keyword | `.setSearchKeyword("john");`                                |
| `setTitleText`              | Sets a custom title in the toolbar                        | `.setTitleText("Contacts");`                                |
| `setSearchPlaceholderText`  | Sets the placeholder text for the search input            | `.setSearchPlaceholderText("Find users...");`               |

* **Verify**: After calling a visibility method, confirm the corresponding UI element is shown or hidden.

## Custom View Slots

Each slot replaces a section of the default UI. Slots that accept a `User` parameter receive the user object for that row via the `UsersViewHolderListener` pattern (`createView` + `bindView`).

| Slot              | Method                                     | Replaces                                      |
| ----------------- | ------------------------------------------ | --------------------------------------------- |
| Leading view      | `setLeadingView(UsersViewHolderListener)`  | Avatar / left section                         |
| Title view        | `setTitleView(UsersViewHolderListener)`    | Name / title text                             |
| Subtitle view     | `setSubtitleView(UsersViewHolderListener)` | Subtitle text below name                      |
| Trailing view     | `setTrailingView(UsersViewHolderListener)` | Right section                                 |
| Item view         | `seItemView(UsersViewHolderListener)`      | Entire list item row (note: typo in SDK)      |
| Loading view      | `setLoadingView(@LayoutRes int)`           | Loading spinner                               |
| Empty view        | `setEmptyView(@LayoutRes int)`             | Empty state                                   |
| Error view        | `setErrorView(@LayoutRes int)`             | Error state                                   |
| Overflow menu     | `setOverflowMenu(View)`                    | Toolbar menu                                  |
| Options (replace) | `setOptions(Function2)`                    | Long-press context menu (replaces defaults)   |
| Options (append)  | `addOptions(Function2)`                    | Long-press context menu (appends to defaults) |

### `setLeadingView`

Replace the avatar / left section.

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

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

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

        @Override
        public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List<User> userList, int position) {

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

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

### `setTitleView`

Replace the name / title text.

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

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

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

        @Override
        public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List<User> userList, int position) {

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

Inline role badge example:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/ubfBSdV1t6rmjxeA/images/868214e2-users_title_view-fffdf84d79897281f81e88aa67701656.png?fit=max&auto=format&n=ubfBSdV1t6rmjxeA&q=85&s=643ec21cabf8fea2ce572e6ea436ea2b" width="1280" height="800" data-path="images/868214e2-users_title_view-fffdf84d79897281f81e88aa67701656.png" />
</Frame>

Create a `custom_user_title_view.xml` layout:

```xml custom_user_title_view.xml lines theme={null}
<?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/role"
        android:layout_width="50dp"
        android:layout_height="15dp"
        android:layout_marginStart="@dimen/cometchat_16dp"
        android:background="@drawable/teacher" />

</LinearLayout>
```

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

        override fun bindView(
            context: Context,
            createdView: View,
            user: User,
            holder: RecyclerView.ViewHolder,
            userList: List<User>,
            position: Int
        ) {
            val layout = createdView.findViewById<LinearLayout>(R.id.user_layout)
            val layoutParams = LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            layout.layoutParams = layoutParams
            val name = createdView.findViewById<TextView>(R.id.title)
            name.text = user.name
            val role = createdView.findViewById<View>(R.id.role)
            when (user.role) {
                "teacher" -> {
                    role.visibility = View.VISIBLE
                    role.background = ResourcesCompat.getDrawable(resources, R.drawable.teacher, null)
                }
                "student" -> {
                    role.visibility = View.VISIBLE
                    role.background = ResourcesCompat.getDrawable(resources, R.drawable.student, null)
                }
                "close_friend" -> {
                    role.visibility = View.VISIBLE
                    role.background = ResourcesCompat.getDrawable(resources, R.drawable.close_friend, null)
                }
                else -> role.visibility = View.GONE
            }
        }
    })
    ```
  </Tab>

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

        @Override
        public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List<User> userList, 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(user.getName());
            View role = createdView.findViewById(R.id.role);
            if ("teacher".equals(user.getRole())) {
                role.setVisibility(View.VISIBLE);
                role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.teacher, null));
            } else if ("student".equals(user.getRole())) {
                role.setVisibility(View.VISIBLE);
                role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.student, null));
            } else if ("close_friend".equals(user.getRole())) {
                role.setVisibility(View.VISIBLE);
                role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.close_friend, null));
            } else {
                role.setVisibility(View.GONE);
            }
        }
    });
    ```
  </Tab>
</Tabs>

### `setSubtitleView`

Replace the subtitle text below the user's name.

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

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

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

        @Override
        public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List<User> userList, int position) {

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

Example with last-active timestamp:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/2JiXkJ8lq6PmPGlJ/images/6e16192f-users_subtitle_view-51f448114408521010b6feb4a5bba41d.png?fit=max&auto=format&n=2JiXkJ8lq6PmPGlJ&q=85&s=6187cd3feabcfd9d04ce76314b70cc87" width="1280" height="800" data-path="images/6e16192f-users_subtitle_view-51f448114408521010b6feb4a5bba41d.png" />
</Frame>

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

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

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

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

### `setTrailingView`

Replace the right section of each user item.

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

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

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

        @Override
        public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List<User> userList, int position) {

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

Role tag badge example:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/Xgdtn9VZPDi47bm-/images/2456c417-users_trailing_view-9bb40a8246e8ebdaf081ac7b26f4fa01.png?fit=max&auto=format&n=Xgdtn9VZPDi47bm-&q=85&s=57cf2dc2086f7063d35a221aecbde028" width="1280" height="800" data-path="images/2456c417-users_trailing_view-9bb40a8246e8ebdaf081ac7b26f4fa01.png" />
</Frame>

Create a `custom_user_tail_view.xml` layout:

```xml custom_user_tail_view.xml lines theme={null}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <View
        android:id="@+id/tag"
        android:layout_width="50dp"
        android:layout_height="15dp"
        android:layout_marginStart="@dimen/cometchat_16dp"
        android:background="@drawable/teacher" />

</LinearLayout>
```

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

        override fun bindView(
            context: Context,
            createdView: View,
            user: User,
            holder: RecyclerView.ViewHolder,
            userList: List<User>,
            position: Int
        ) {
            val role = createdView.findViewById<View>(R.id.tag)
            if ("pro" == user.role) {
                role.visibility = View.VISIBLE
                role.background = ResourcesCompat.getDrawable(resources, R.drawable.teacher, null)
            } else {
                role.visibility = View.GONE
            }
        }
    })
    ```
  </Tab>

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

        @Override
        public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List<User> userList, int position) {
            View role = createdView.findViewById(R.id.tag);
            if ("pro".equals(user.getRole())) {
                role.setVisibility(View.VISIBLE);
                role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.teacher, null));
            } else {
                role.setVisibility(View.GONE);
            }
        }
    });
    ```
  </Tab>
</Tabs>

### `setItemView`

Replace the entire list item row.

<Note>
  The Java method name is `seItemView` (note the missing 't'). This is a known typo in the SDK. In Kotlin, property access syntax normalizes this.
</Note>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatUsers.seItemView(object : UsersViewHolderListener() {
        override fun createView(
            context: Context?,
            listItem: CometchatListBaseItemsBinding?
        ): View? {
            return null
        }

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

  <Tab title="Java">
    ```java lines theme={null}
    cometchatUsers.seItemView(new UsersViewHolderListener() {
        @Override
        public View createView(Context context, CometchatListBaseItemsBinding listItem) {
            return null;
        }

        @Override
        public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List<User> userList, int position) {

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

Example with online status background:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/OOBJyP9hM0C-rAe_/images/de656dc8-users_list_item_view-e66a444aac7edcb18dec787a42b646c3.png?fit=max&auto=format&n=OOBJyP9hM0C-rAe_&q=85&s=33c92766d69cc7e841020d6c921ef90d" width="1280" height="800" data-path="images/de656dc8-users_list_item_view-e66a444aac7edcb18dec787a42b646c3.png" />
</Frame>

Create a `custom_list_item_view.xml` layout:

```xml custom_list_item_view.xml lines theme={null}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/parent_lay"
    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_marginTop="@dimen/cometchat_padding_3"
        android:layout_marginEnd="@dimen/cometchat_padding_4"
        android:layout_marginBottom="@dimen/cometchat_padding_3"
        android:gravity="center_vertical"
        android:orientation="horizontal">

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

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

        </androidx.constraintlayout.widget.ConstraintLayout>

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

    </LinearLayout>

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

</LinearLayout>
```

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

        override fun bindView(
            context: Context,
            createdView: View,
            user: User,
            holder: RecyclerView.ViewHolder,
            userList: List<User>,
            position: Int
        ) {
            val avatar = createdView.findViewById<CometChatAvatar>(R.id.custom_avatar)
            val title = createdView.findViewById<TextView>(R.id.tvName)
            val parentLayout = createdView.findViewById<LinearLayout>(R.id.parent_lay)
            val name = user.name
            title.text = name
            avatar.setStyle(com.cometchat.chatuikit.R.style.CometChatAvatarStyle)
            avatar.avatarPlaceHolderTextAppearance =
                com.cometchat.chatuikit.R.style.CometChatTextAppearanceHeading4_Bold
            avatar.setAvatar(name, user.avatar)
            if (user.status == UIKitConstants.UserStatus.ONLINE) {
                parentLayout.setBackgroundColor(Color.parseColor("#E6F4ED"))
            } else {
                parentLayout.setBackgroundColor(Color.parseColor("#00000000"))
            }
        }
    })
    ```
  </Tab>

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

        @Override
        public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List<User> userList, int position) {
            CometChatAvatar avatar = createdView.findViewById(R.id.custom_avatar);
            TextView title = createdView.findViewById(R.id.tvName);
            LinearLayout parentLayout = createdView.findViewById(R.id.parent_lay);
            String name = user.getName();
            title.setText(name);
            avatar.setStyle(com.cometchat.chatuikit.R.style.CometChatAvatarStyle);
            avatar.setAvatarPlaceHolderTextAppearance(com.cometchat.chatuikit.R.style.CometChatTextAppearanceHeading4_Bold);
            avatar.setAvatar(name, user.getAvatar());
            if (user.getStatus().equals(UIKitConstants.UserStatus.ONLINE)) {
                parentLayout.setBackgroundColor(Color.parseColor("#E6F4ED"));
            } else {
                parentLayout.setBackgroundColor(Color.parseColor("#00000000"));
            }
        }
    });
    ```
  </Tab>
</Tabs>

### `setOptions`

Replace the long-press context menu entirely.

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

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

### `addOptions`

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

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

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

### `setLoadingView`

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

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

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

### `setEmptyView`

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

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

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

### `setErrorView`

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

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

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

### `setOverflowMenu`

Replace the toolbar overflow menu.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/le8ibYc8lBJsShSE/images/50473531-user_menu-5b7eb7088d966ada9e751e591dbee212.png?fit=max&auto=format&n=le8ibYc8lBJsShSE&q=85&s=62a58348cde075a890d58f68a12a7ee3" width="1280" height="800" data-path="images/50473531-user_menu-5b7eb7088d966ada9e751e591dbee212.png" />
</Frame>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val imageView = ImageView(requireContext())
    imageView.setImageResource(R.drawable.ic_user_menu)
    cometchatUsers.setOverflowMenu(imageView)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    ImageView imageView = new ImageView(requireContext());
    imageView.setImageResource(R.drawable.ic_user_menu);
    cometchatUsers.setOverflowMenu(imageView);
    ```
  </Tab>
</Tabs>

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

## Common Patterns

### Hide all chrome — minimal list

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometChatUsers.setUserStatusVisibility(View.GONE)
    cometChatUsers.setSeparatorVisibility(View.GONE)
    cometChatUsers.setToolbarVisibility(View.GONE)
    cometChatUsers.setStickyHeaderVisibility(View.GONE)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometChatUsers.setUserStatusVisibility(View.GONE);
    cometChatUsers.setSeparatorVisibility(View.GONE);
    cometChatUsers.setToolbarVisibility(View.GONE);
    cometChatUsers.setStickyHeaderVisibility(View.GONE);
    ```
  </Tab>
</Tabs>

### Friends-only list

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = UsersRequest.UsersRequestBuilder()
        .friendsOnly(true)
    cometChatUsers.setUsersRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    UsersRequest.UsersRequestBuilder builder = new UsersRequest.UsersRequestBuilder()
        .friendsOnly(true);
    cometChatUsers.setUsersRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

### Online users only

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = UsersRequest.UsersRequestBuilder()
        .setUserStatus(CometChatConstants.USER_STATUS_ONLINE)
    cometChatUsers.setUsersRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    UsersRequest.UsersRequestBuilder builder = new UsersRequest.UsersRequestBuilder()
        .setUserStatus(CometChatConstants.USER_STATUS_ONLINE);
    cometChatUsers.setUsersRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

## Advanced Methods

### Programmatic Selection

#### `selectUser`

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

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

    // Select a user in multi-select mode
    cometChatUsers.selectUser(user, UIKitConstants.SelectionMode.MULTIPLE)
    ```
  </Tab>

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

    // Select a user in multi-select mode
    cometChatUsers.selectUser(user, UIKitConstants.SelectionMode.MULTIPLE);
    ```
  </Tab>
</Tabs>

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

#### `clearSelection`

Clears all selected users and resets the selection UI.

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

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

#### `getSelectedUsers`

Returns the list of currently selected `User` objects.

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

  <Tab title="Java">
    ```java lines theme={null}
    List<User> selected = cometChatUsers.getSelectedUsers();
    ```
  </Tab>
</Tabs>

### Selected Users List

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

| Method                              | Type                             | Description                             |
| ----------------------------------- | -------------------------------- | --------------------------------------- |
| `setSelectedUsersListVisibility`    | `int (View.VISIBLE / View.GONE)` | Show or hide the selected users strip   |
| `setSelectedUserAvatarStyle`        | `@StyleRes int`                  | Avatar style for selected user chips    |
| `setSelectedUserItemTextColor`      | `@ColorInt int`                  | Text color for selected user names      |
| `setSelectedUserItemTextAppearance` | `@StyleRes int`                  | Text appearance for selected user names |
| `setSelectedUserItemRemoveIcon`     | `Drawable`                       | Icon for the remove button on each chip |
| `setSelectedUserItemRemoveIconTint` | `@ColorInt int`                  | Tint color for the remove icon          |

### Search Input Customization

The built-in search box can be customized programmatically:

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

### Internal Access

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

| Method                     | Returns                    | Description                                     |
| -------------------------- | -------------------------- | ----------------------------------------------- |
| `getBinding()`             | `CometchatUserListBinding` | The ViewBinding for the component's root layout |
| `getViewModel()`           | `UsersViewModel`           | The ViewModel managing user data and state      |
| `getUsersAdapter()`        | `UsersAdapter`             | The adapter powering the RecyclerView           |
| `setAdapter(UsersAdapter)` | `void`                     | Replaces the default adapter with a custom one  |

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

## Style

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

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/G6Puyz_3Zlaowa9R/images/c8909b74-users_styling-3acb1ffef7870b6903a070fd83b5103f.png?fit=max&auto=format&n=G6Puyz_3Zlaowa9R&q=85&s=18397b1b8f7cf63001b55db0f37d161d" width="1280" height="800" data-path="images/c8909b74-users_styling-3acb1ffef7870b6903a070fd83b5103f.png" />
</Frame>

```xml themes.xml lines theme={null}
    <style name="CustomAvatarStyle" parent="CometChatAvatarStyle">
        <item name="cometchatAvatarStrokeRadius">8dp</item>
        <item name="cometchatAvatarBackgroundColor">#FBAA75</item>
    </style>
    <style name="CustomUsersStyle" parent="CometChatUsersStyle">
        <item name="cometchatUsersAvatarStyle">@style/CustomAvatarStyle</item>
        <item name="cometchatUsersSeparatorColor">#F76808</item>
        <item name="cometchatUsersTitleTextColor">#F76808</item>
    </style>
```

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

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

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

### Programmatic Style Properties

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

| Method                                | Type             | Description                                  |
| ------------------------------------- | ---------------- | -------------------------------------------- |
| `setBackgroundColor`                  | `@ColorInt int`  | Background color of the component            |
| `setBackIconTint`                     | `@ColorInt int`  | Tint color for the back icon                 |
| `setBackIcon`                         | `Drawable`       | Custom back icon drawable                    |
| `setTitleTextColor`                   | `@ColorInt int`  | Title text color in the toolbar              |
| `setTitleTextAppearance`              | `@StyleRes int`  | Title text appearance in the toolbar         |
| `setItemTitleTextColor`               | `@ColorInt int`  | Text color for user item titles              |
| `setItemTitleTextAppearance`          | `@StyleRes int`  | Text appearance for user item titles         |
| `setItemBackgroundColor`              | `@ColorInt int`  | Background color for list items              |
| `setItemSelectedBackgroundColor`      | `@ColorInt int`  | Background color for selected list items     |
| `setSeparatorColor`                   | `@ColorInt int`  | Color of list item separators                |
| `setStrokeColor`                      | `@ColorInt int`  | Stroke color of the component border         |
| `setStrokeWidth`                      | `@Dimension int` | Stroke width of the component border         |
| `setCornerRadius`                     | `@Dimension int` | Corner radius of the component               |
| `setStickyTitleColor`                 | `@ColorInt int`  | Text color for sticky alphabetical headers   |
| `setStickyTitleAppearance`            | `@StyleRes int`  | Text appearance for sticky headers           |
| `setStickyTitleBackgroundColor`       | `@ColorInt int`  | Background color for sticky headers          |
| `setEmptyStateTextColor`              | `@ColorInt int`  | Title text color for the empty state         |
| `setEmptyStateTextAppearance`         | `@StyleRes int`  | Title text appearance for the empty state    |
| `setEmptyStateSubtitleTextColor`      | `@ColorInt int`  | Subtitle text color for the empty state      |
| `setEmptyStateSubTitleTextAppearance` | `@StyleRes int`  | Subtitle text appearance for the empty state |
| `setErrorStateTextColor`              | `@ColorInt int`  | Title text color for the error state         |
| `setErrorStateTextAppearance`         | `@StyleRes int`  | Title text appearance for the error state    |
| `setErrorStateSubtitleColor`          | `@ColorInt int`  | Subtitle text color for the error state      |
| `setErrorStateSubtitleTextAppearance` | `@StyleRes int`  | Subtitle text appearance for the error state |
| `setRetryButtonTextColor`             | `@ColorInt int`  | Text color for the retry button              |
| `setRetryButtonTextAppearance`        | `@StyleRes int`  | Text appearance for the retry button         |
| `setRetryButtonBackgroundColor`       | `@ColorInt int`  | Background color for the retry button        |
| `setRetryButtonStrokeColor`           | `@ColorInt int`  | Stroke color for the retry button            |
| `setRetryButtonStrokeWidth`           | `@Dimension int` | Stroke width for the retry button            |
| `setRetryButtonCornerRadius`          | `@Dimension int` | Corner radius for the retry button           |
| `setAvatarStyle`                      | `@StyleRes int`  | Style for user avatars                       |
| `setStatusIndicatorStyle`             | `@StyleRes int`  | Style for online/offline status indicators   |

### Checkbox Style Properties (Selection Mode)

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

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

## Customization Matrix

| What to change                           | Where             | Property/API                               | Example                                                     |
| ---------------------------------------- | ----------------- | ------------------------------------------ | ----------------------------------------------------------- |
| Override behavior on user interaction    | Activity/Fragment | `setOn<Event>` callbacks                   | `setOnItemClick((v, pos, u) -> { ... })`                    |
| Filter which users appear                | Activity/Fragment | `setUsersRequestBuilder`                   | `setUsersRequestBuilder(builder)`                           |
| Customize search results                 | Activity/Fragment | `setSearchRequestBuilder`                  | `setSearchRequestBuilder(builder)`                          |
| Toggle visibility of UI elements         | Activity/Fragment | `set<Feature>Visibility(int)`              | `setUserStatusVisibility(View.GONE)`                        |
| Replace a section of the list item       | Activity/Fragment | `set<Slot>View`                            | `setLeadingView(listener)`                                  |
| Change colors, fonts, spacing            | `themes.xml`      | `CometChatUsersStyle`                      | `<item name="cometchatUsersSeparatorColor">#F76808</item>`  |
| Avatar style (corner radius, background) | `themes.xml`      | `cometchatUsersAvatarStyle`                | `<item name="cometchatAvatarStrokeRadius">8dp</item>`       |
| Apply a custom style                     | Activity/Fragment | `setStyle(int styleRes)`                   | `cometChatUsers.setStyle(R.style.CustomUsersStyle);`        |
| Back button visibility                   | Activity/Fragment | `setBackIconVisibility(int)`               | `.setBackIconVisibility(View.VISIBLE);`                     |
| Toolbar visibility                       | Activity/Fragment | `setToolbarVisibility(int)`                | `.setToolbarVisibility(View.GONE);`                         |
| Sticky header visibility                 | Activity/Fragment | `setStickyHeaderVisibility(int)`           | `.setStickyHeaderVisibility(View.GONE);`                    |
| Error state visibility                   | Activity/Fragment | `setErrorStateVisibility(int)`             | `.setErrorStateVisibility(View.GONE);`                      |
| Empty state visibility                   | Activity/Fragment | `setEmptyStateVisibility(int)`             | `.setEmptyStateVisibility(View.GONE);`                      |
| Loading state visibility                 | Activity/Fragment | `setLoadingStateVisibility(int)`           | `.setLoadingStateVisibility(View.GONE);`                    |
| Separator visibility                     | Activity/Fragment | `setSeparatorVisibility(int)`              | `.setSeparatorVisibility(View.GONE);`                       |
| User online status visibility            | Activity/Fragment | `setUserStatusVisibility(int)`             | `.setUserStatusVisibility(View.GONE);`                      |
| Selection mode (single/multiple)         | Activity/Fragment | `setSelectionMode(SelectionMode)`          | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` |
| Search keyword                           | Activity/Fragment | `setSearchKeyword(String)`                 | `.setSearchKeyword("john");`                                |
| Search box visibility                    | Activity/Fragment | `setSearchBoxVisibility(int)`              | `.setSearchBoxVisibility(View.GONE);`                       |
| Custom toolbar title                     | Activity/Fragment | `setTitleText(String)`                     | `.setTitleText("Contacts");`                                |
| Search placeholder                       | Activity/Fragment | `setSearchPlaceholderText(String)`         | `.setSearchPlaceholderText("Find users...");`               |
| Long-press options (replace)             | Activity/Fragment | `setOptions(Function2)`                    | See `setOptions` code above                                 |
| Long-press options (append)              | Activity/Fragment | `addOptions(Function2)`                    | See `addOptions` code above                                 |
| Loading view                             | Activity/Fragment | `setLoadingView(int)`                      | `.setLoadingView(R.layout.your_loading_view);`              |
| Empty view                               | Activity/Fragment | `setEmptyView(int)`                        | `.setEmptyView(R.layout.your_empty_view);`                  |
| Error view                               | Activity/Fragment | `setErrorView(int)`                        | `.setErrorView(R.layout.your_error_view);`                  |
| Leading view (avatar area)               | Activity/Fragment | `setLeadingView(UsersViewHolderListener)`  | See `setLeadingView` code above                             |
| Title view                               | Activity/Fragment | `setTitleView(UsersViewHolderListener)`    | See `setTitleView` code above                               |
| Trailing view                            | Activity/Fragment | `setTrailingView(UsersViewHolderListener)` | See `setTrailingView` code above                            |
| Entire list item                         | Activity/Fragment | `setItemView(UsersViewHolderListener)`     | See `setItemView` code above                                |
| Subtitle view                            | Activity/Fragment | `setSubtitleView(UsersViewHolderListener)` | See `setSubtitleView` code above                            |
| Overflow menu                            | Activity/Fragment | `setOverflowMenu(View)`                    | `cometChatUsers.setOverflowMenu(view);`                     |
| Programmatic selection                   | Activity/Fragment | `selectUser(User, SelectionMode)`          | `.selectUser(user, SelectionMode.SINGLE);`                  |
| Clear selection                          | Activity/Fragment | `clearSelection()`                         | `.clearSelection();`                                        |
| Selected users strip                     | Activity/Fragment | `setSelectedUsersListVisibility(int)`      | `.setSelectedUsersListVisibility(View.VISIBLE);`            |
| Internal adapter access                  | Activity/Fragment | `getUsersAdapter()` / `setAdapter()`       | Advanced use only                                           |

## Next Steps

<CardGroup cols={2}>
  <Card title="Conversations" icon="comments" href="/ui-kit/android/conversations">
    Browse recent conversations
  </Card>

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

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

  <Card title="Theming" icon="paintbrush" href="/ui-kit/android/theme-introduction">
    Customize colors, fonts, and styles
  </Card>
</CardGroup>
