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

# Call Logs

> Scrollable list of call logs for the logged-in user with caller names, avatars, call status, and timestamps.

<Accordion title="AI Integration Quick Reference">
  ```json theme={null}
  {
    "component": "CometChatCallLogs",
    "package": "com.cometchat.chatuikit.calls.calllogs",
    "xmlElement": "<com.cometchat.chatuikit.calls.calllogs.CometChatCallLogs />",
    "description": "Scrollable list of call logs for the logged-in user with caller names, avatars, call status, and timestamps.",
    "primaryOutput": {
      "method": "setOnItemClick",
      "type": "OnItemClick<CallLog>"
    },
    "methods": {
      "data": {
        "setCallLogRequestBuilder": {
          "type": "CallLogRequest.CallLogRequestBuilder",
          "default": "SDK default",
          "note": "Pass the builder, not the result of .build()"
        }
      },
      "callbacks": {
        "setOnItemClick": "OnItemClick<CallLog>",
        "setOnItemLongClick": "OnItemLongClick<CallLog>",
        "setOnBackPressListener": "OnBackPress",
        "setOnCallIconClickListener": "OnCallIconClick",
        "setOnError": "OnCallError",
        "setOnLoad": "OnLoad<CallLog>",
        "setOnEmpty": "OnEmpty"
      },
      "visibility": {
        "setToolbarVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" },
        "setBackIconVisibility": { "type": "int", "default": "View.GONE" },
        "setLoadingStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setErrorStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setEmptyStateVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setSeparatorVisibility": { "type": "int", "default": "View.VISIBLE" },
        "setTitleVisibility": { "type": "int", "default": "View.VISIBLE" }
      },
      "viewSlots": {
        "setItemView": "CallLogsViewHolderListener — entire list item row",
        "setLeadingView": "CallLogsViewHolderListener — avatar / left section",
        "setTitleView": "CallLogsViewHolderListener — name / title text",
        "setSubtitleView": "CallLogsViewHolderListener — subtitle text below name",
        "setTrailingView": "CallLogsViewHolderListener — right section",
        "setLoadingView": "@LayoutRes int — loading spinner",
        "setEmptyView": "@LayoutRes int — empty state",
        "setErrorView": "@LayoutRes int — error state",
        "setOptions": "Function2<Context, CallLog, List<MenuItem>> — long-press context menu (replaces defaults)",
        "setAddOptions": "Function2<Context, CallLog, List<MenuItem>> — long-press context menu (appends to defaults)"
      },
      "advanced": {
        "refreshCallLogs": "void — re-fetches call logs from the server",
        "setDateFormat": "SimpleDateFormat — legacy date format setter",
        "setDateTimeFormatter": "DateTimeFormatterCallback — custom date/time formatting",
        "getBinding": "CometchatCallLogsBinding — root ViewBinding",
        "getViewModel": "CallLogsViewModel — internal ViewModel access",
        "getAdapter": "CallLogsAdapter — internal adapter access",
        "setAdapter": "CallLogsAdapter — replace the default adapter"
      },
      "style": {
        "setStyle": {
          "type": "@StyleRes int",
          "parent": "CometChatCallLogsStyle"
        }
      }
    },
    "events": [],
    "sdkListeners": []
  }
  ```
</Accordion>

## Where It Fits

`CometChatCallLogs` is a list component. It renders all call logs for the logged-in user and emits the selected `CallLog` via `setOnItemClick`. Wire it to a call detail screen or use `setOnCallIconClickListener` to initiate a callback.

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

        private lateinit var callLogs: CometChatCallLogs

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

            callLogs = findViewById(R.id.call_log)

            callLogs.setOnItemClick { view, position, callLog ->
                // Navigate to call detail screen with the selected callLog
            }

            callLogs.setOnCallIconClickListener { view, holder, position, callLog ->
                // Initiate a call using the callLog data
            }
        }
    }
    ```
  </Tab>

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

        private CometChatCallLogs callLogs;

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

            callLogs = findViewById(R.id.call_log);

            callLogs.setOnItemClick((view, position, callLog) -> {
                // Navigate to call detail screen with the selected callLog
            });

            callLogs.setOnCallIconClickListener((view, holder, position, callLog) -> {
                // Initiate a call using the callLog data
            });
        }
    }
    ```
  </Tab>
</Tabs>

## Quick Start

Add the component to your layout XML:

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

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/Gp90C5sdVtuRR4t7/images/7fe2a6db-call_logs-7b4f502153923374898f3887441ab8d2.png?fit=max&auto=format&n=Gp90C5sdVtuRR4t7&q=85&s=14435b9084f986487b17304c759a86a2" width="1280" height="800" data-path="images/7fe2a6db-call_logs-7b4f502153923374898f3887441ab8d2.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(CometChatCallLogs(this))
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new CometChatCallLogs(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 CometChatCallLogs(requireContext())
    }
    ```
  </Tab>

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

## Filtering Call Logs

Pass a `CallLogRequest.CallLogRequestBuilder` to `setCallLogRequestBuilder`. Pass the builder instance — not the result of `.build()`.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = CallLogRequest.CallLogRequestBuilder()
        .setLimit(20)
        .setHasRecording(true)
    cometchatCallLogs.setCallLogRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    CallLogRequest.CallLogRequestBuilder builder = new CallLogRequest.CallLogRequestBuilder()
        .setLimit(20)
        .setHasRecording(true);
    cometchatCallLogs.setCallLogRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

### Filter Recipes

| Recipe                  | Code                                                                |
| ----------------------- | ------------------------------------------------------------------- |
| Limit to 20 per page    | `builder.setLimit(20)`                                              |
| Audio calls only        | `builder.setCallType(CometChatCallsConstants.CALL_TYPE_AUDIO)`      |
| Video calls only        | `builder.setCallType(CometChatCallsConstants.CALL_TYPE_VIDEO)`      |
| Missed calls only       | `builder.setCallStatus(CometChatCallsConstants.CALL_STATUS_MISSED)` |
| Calls with recordings   | `builder.setHasRecording(true)`                                     |
| Incoming calls only     | `builder.setCallDirection("incoming")`                              |
| Outgoing calls only     | `builder.setCallDirection("outgoing")`                              |
| Filter by user UID      | `builder.setUid("uid1")`                                            |
| Filter by group GUID    | `builder.setGuid("guid1")`                                          |
| Filter by call category | `builder.setCallCategory("call")`                                   |

> The component uses infinite scroll — the next page loads as the user scrolls to the bottom.

## Actions and Events

### Callback Methods

#### `setOnItemClick`

Fires when a call log row is tapped. Primary navigation hook — use to open a call detail screen.

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

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

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

#### `setOnItemLongClick`

Fires when a call log row is long-pressed. Use for additional actions like delete or call back.

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

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

    });
    ```
  </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}
    cometchatCallLogs.onBackPressListener = OnBackPress {

    }
    ```
  </Tab>

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

#### `setOnCallIconClickListener`

Fires when the user taps the audio or video call icon on a call log item. Use to initiate a call or navigate to a call screen.

Interface: `void onCallIconClick(View view, CallLogsAdapter.CallLogsViewHolder holder, int position, CallLog callLog)`

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatCallLogs.setOnCallIconClickListener { view, holder, position, callLog ->
        // Handle call icon click
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatCallLogs.setOnCallIconClickListener((view, holder, position, callLog) -> {
        // Handle call icon click
    });
    ```
  </Tab>
</Tabs>

#### `setOnError`

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

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

    }
    ```
  </Tab>

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

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

#### `setOnLoad`

Fires when the list is successfully fetched and loaded.

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

        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatCallLogs.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}
    cometchatCallLogs.setOnEmpty {
                
    }
    ```
  </Tab>

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

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

### Global UI Events

The `CometChatCallLogs` component does not have any exposed global UI events.

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

The `CometChatCallLogs` component does not listen to any SDK events internally. Call logs are fetched on load and can be refreshed manually with `refreshCallLogs()`.

## Functionality

Small functional customizations such as toggling visibility of UI elements.

| Methods                     | Description                                           | Code                                     |
| --------------------------- | ----------------------------------------------------- | ---------------------------------------- |
| `setToolbarVisibility`      | Toggles visibility for the toolbar in the app bar     | `.setToolbarVisibility(View.GONE);`      |
| `setBackIconVisibility`     | Toggles visibility for the back button in the app bar | `.setBackIconVisibility(View.VISIBLE);`  |
| `setLoadingStateVisibility` | Hides the loading state while fetching call logs      | `.setLoadingStateVisibility(View.GONE);` |
| `setErrorStateVisibility`   | Hides the error state on fetching call logs           | `.setErrorStateVisibility(View.GONE);`   |
| `setEmptyStateVisibility`   | Hides the empty state on fetching call logs           | `.setEmptyStateVisibility(View.GONE);`   |
| `setSeparatorVisibility`    | Controls visibility of separators in the list view    | `.setSeparatorVisibility(View.GONE);`    |
| `setTitleVisibility`        | Controls visibility of the title in the toolbar       | `.setTitleVisibility(View.GONE);`        |

* **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 `CallLog` parameter receive the call log object for that row via the `CallLogsViewHolderListener` pattern (`createView` + `bindView`).

| Slot              | Method                                        | Replaces                                      |
| ----------------- | --------------------------------------------- | --------------------------------------------- |
| Leading view      | `setLeadingView(CallLogsViewHolderListener)`  | Avatar / left section                         |
| Title view        | `setTitleView(CallLogsViewHolderListener)`    | Name / title text                             |
| Subtitle view     | `setSubtitleView(CallLogsViewHolderListener)` | Subtitle text below name                      |
| Trailing view     | `setTrailingView(CallLogsViewHolderListener)` | Right section                                 |
| Item view         | `setItemView(CallLogsViewHolderListener)`     | Entire list item row                          |
| Loading view      | `setLoadingView(@LayoutRes int)`              | Loading spinner                               |
| Empty view        | `setEmptyView(@LayoutRes int)`                | Empty state                                   |
| Error view        | `setErrorView(@LayoutRes int)`                | Error state                                   |
| Options (replace) | `setOptions(Function2)`                       | Long-press context menu (replaces defaults)   |
| Options (append)  | `setAddOptions(Function2)`                    | Long-press context menu (appends to defaults) |

### `setLeadingView`

Replace the avatar / left section.

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

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

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

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {

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

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

Example with call direction icons:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/TO10Bmu50bb5qPTI/images/2d1b8f1f-calls_leading_view-f16178cad5831b68b69386bddd17ac97.png?fit=max&auto=format&n=TO10Bmu50bb5qPTI&q=85&s=21724ad3d838bd37b62514b09f134d98" width="2560" height="1600" data-path="images/2d1b8f1f-calls_leading_view-f16178cad5831b68b69386bddd17ac97.png" />
</Frame>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatCallLogs.setLeadingView(object : CallLogsViewHolderListener() {
        override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View {
            return CometChatAvatar(context)
        }

        override fun bindView(
            context: Context,
            createdView: View,
            callLog: CallLog,
            holder: RecyclerView.ViewHolder,
            callList: List<CallLog>,
            position: Int
        ) {
            val avatar = createdView as CometChatAvatar

            if (callLog.initiator is CallUser) {
                val initiator = callLog.initiator as CallUser
                val isLoggedInUser = CallUtils.isLoggedInUser(initiator)
                val isMissedOrUnanswered = callLog.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (callLog
                    .status
                    == CometChatCallsConstants.CALL_STATUS_MISSED)

                if (callLog.type == CometChatCallsConstants.CALL_TYPE_AUDIO || (callLog
                        .type
                        == CometChatCallsConstants.CALL_TYPE_VIDEO) || callLog.type == CometChatCallsConstants.CALL_TYPE_AUDIO_VIDEO
                ) {
                    if (isLoggedInUser) {
                        avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.outgoing_voice_call, null)!!)
                    } else if (isMissedOrUnanswered) {
                        avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.miss_call, null)!!)
                    } else {
                        avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.incoming_voice_call, null)!!)
                    }
                }
            }
            val layoutParams = LinearLayout.LayoutParams(
                Utils.convertDpToPx(context, 50),
                Utils.convertDpToPx(context, 50)
            )
            avatar.layoutParams = layoutParams
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatCallLogs.setLeadingView(new CallLogsViewHolderListener() {
        @Override
        public View createView(Context context, CometchatCallLogsItemsBinding listItem) {
            return new CometChatAvatar(context);
        }

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {
            CometChatAvatar avatar = (CometChatAvatar) createdView;

            if (callLog.getInitiator() instanceof CallUser) {
                CallUser initiator = (CallUser) callLog.getInitiator();
                boolean isLoggedInUser = CallUtils.isLoggedInUser(initiator);
                boolean isMissedOrUnanswered = callLog.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || callLog
                    .getStatus()
                    .equals(CometChatCallsConstants.CALL_STATUS_MISSED);

                if (callLog.getType().equals(CometChatCallsConstants.CALL_TYPE_AUDIO) || callLog
                    .getType()
                    .equals(CometChatCallsConstants.CALL_TYPE_VIDEO) || callLog.getType().equals(CometChatCallsConstants.CALL_TYPE_AUDIO_VIDEO)) {

                    if (isLoggedInUser) {
                        avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.outgoing_voice_call, null));
                    } else if (isMissedOrUnanswered) {
                        avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.miss_call, null));
                    } else {
                        avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.incoming_voice_call, null));
                    }
                }
            }
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                Utils.convertDpToPx(context, 50),
                Utils.convertDpToPx(context, 50)
            );
            avatar.setLayoutParams(layoutParams);
        }
    });
    ```
  </Tab>
</Tabs>

### `setTitleView`

Replace the name / title text.

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

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

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

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {

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

Inline call duration example:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/2JiXkJ8lq6PmPGlJ/images/70338d8e-calls_title_view-284a29cf898ed446cd6b56b480dba55e.png?fit=max&auto=format&n=2JiXkJ8lq6PmPGlJ&q=85&s=f7d0722df0f599dccde6e76336015e1a" width="2560" height="1600" data-path="images/70338d8e-calls_title_view-284a29cf898ed446cd6b56b480dba55e.png" />
</Frame>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatCallLogs.setTitleView(object : CallLogsViewHolderListener() {
        override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View {
            return TextView(context)
        }

        override fun bindView(
            context: Context,
            createdView: View,
            callLog: CallLog,
            holder: RecyclerView.ViewHolder,
            callList: List<CallLog>,
            position: Int
        ) {
            val textView = createdView as TextView
            textView.setTextAppearance(CometChatTheme.getTextAppearanceHeading4Regular(context))
            textView.setTextColor(CometChatTheme.getTextColorPrimary(context))
            CallUtils.getCallLogUserName(callLog)
            if (callLog.totalDurationInMinutes > 0) {
                val duration = callLog.totalDurationInMinutes.toString()
                textView.text = CallUtils.getCallLogUserName(callLog) + " • \uD83D\uDD5A\uFE0F " + duration
                    .substring(0, if (duration.length > 4) 4 else 3) + " mins"
            } else textView.text = CallUtils.getCallLogUserName(callLog)
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatCallLogs.setTitleView(new CallLogsViewHolderListener() {
        @Override
        public View createView(Context context, CometchatCallLogsItemsBinding listItem) {
            return new TextView(context);
        }

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {
            TextView textView = (TextView) createdView;
            textView.setTextAppearance(CometChatTheme.getTextAppearanceHeading4Regular(context));
            textView.setTextColor(CometChatTheme.getTextColorPrimary(context));
            CallUtils.getCallLogUserName(callLog);
            if (callLog.getTotalDurationInMinutes() > 0) {
                String duration = String.valueOf(callLog.getTotalDurationInMinutes());
                textView.setText(CallUtils.getCallLogUserName(callLog) + " • \uD83D\uDD5A\uFE0F " + duration
                    .substring(0, duration.length() > 4 ? 4 : 3) + " mins");
            } else textView.setText(CallUtils.getCallLogUserName(callLog));
        }
    });
    ```
  </Tab>
</Tabs>

### `setSubtitleView`

Replace the subtitle text below the caller's name.

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

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

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

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {

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

Example with call direction text:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/FGBCGWXGo5d9bVxR/images/c0c5e53a-calls_subtitle_view-23dbb0f58400e2d8e4b4b1112eb75757.png?fit=max&auto=format&n=FGBCGWXGo5d9bVxR&q=85&s=1f8fea540f5a05a434e300224a6ae102" width="1280" height="800" data-path="images/c0c5e53a-calls_subtitle_view-23dbb0f58400e2d8e4b4b1112eb75757.png" />
</Frame>

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

        override fun bindView(
            context: Context,
            createdView: View,
            callLog: CallLog,
            holder: RecyclerView.ViewHolder,
            callList: List<CallLog>,
            position: Int
        ) {
            val textView = createdView as TextView
            val callUser = callLog.initiator as CallUser
            val isInitiator = callUser.uid == CometChat.getLoggedInUser().uid
            if (callLog.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (callLog
                    .status
                    == CometChatCallsConstants.CALL_STATUS_MISSED)
            ) {
                textView.text = "Missed Call"
            } else {
                if (isInitiator) {
                    textView.text = "Outgoing Call"
                } else {
                    textView.text = "Incoming Call"
                }
            }
        }
    })
    ```
  </Tab>

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

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {
            TextView textView = (TextView) createdView;
            CallUser callUser = (CallUser) callLog.getInitiator();
            boolean isInitiator = callUser.getUid().equals(CometChat.getLoggedInUser().getUid());
            if (callLog.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || callLog
                .getStatus()
                .equals(CometChatCallsConstants.CALL_STATUS_MISSED)) {
                textView.setText("Missed Call");
            } else {
                if (isInitiator) {
                    textView.setText("Outgoing Call");
                } else {
                    textView.setText("Incoming Call");
                }
            }
        }
    });
    ```
  </Tab>
</Tabs>

### `setTrailingView`

Replace the right section of each call log item.

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

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

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

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {

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

Timestamp example:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/fxK75AS6FzDL1Oqo/images/b471a86b-calls_tail_view-c2c6951de1fd0e56ac3a8b3038fea648.png?fit=max&auto=format&n=fxK75AS6FzDL1Oqo&q=85&s=9f4d8bacd54e4777cf2d69f737642e45" width="1280" height="800" data-path="images/b471a86b-calls_tail_view-c2c6951de1fd0e56ac3a8b3038fea648.png" />
</Frame>

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatCallLogs.setTrailingView(object : CallLogsViewHolderListener() {
        override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View {
            return TextView(context)
        }

        override fun bindView(
            context: Context,
            createdView: View,
            callLog: CallLog,
            holder: RecyclerView.ViewHolder,
            callList: List<CallLog>,
            position: Int
        ) {
            val textView = createdView as TextView
            textView.text = SimpleDateFormat("dd MMM, hh:mm a").format(callLog.initiatedAt * 1000)
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java YourActivity.java lines theme={null}
    cometchatCallLogs.setTrailingView(new CallLogsViewHolderListener() {
        @Override
        public View createView(Context context, CometchatCallLogsItemsBinding listItem) {
            return new TextView(context);
        }

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {
            TextView textView = (TextView) createdView;
            textView.setText(new SimpleDateFormat("dd MMM, hh:mm a").format(callLog.getInitiatedAt() * 1000));
        }
    });
    ```
  </Tab>
</Tabs>

### `setItemView`

Replace the entire list item row.

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

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

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

        @Override
        public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {

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

Example with custom call log layout:

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/Xgdtn9VZPDi47bm-/images/26e76652-calls_list_item_view-6ab3eea9c5769eac919d78b5a358ae7a.png?fit=max&auto=format&n=Xgdtn9VZPDi47bm-&q=85&s=d13874c5a43c4ecaf8da73d2cfcf8213" width="1280" height="800" data-path="images/26e76652-calls_list_item_view-6ab3eea9c5769eac919d78b5a358ae7a.png" />
</Frame>

Create a `call_log_list_item.xml` custom layout file:

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

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

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/cometchat_margin_3"
        android:layout_marginEnd="@dimen/cometchat_margin_3"
        android:gravity="center_vertical"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="1" />

        <TextView
            android:id="@+id/tv_subtitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?attr/cometchatTextAppearanceBodyRegular"
            android:textColor="?attr/cometchatTextColorSecondary" />

    </LinearLayout>

    <Space
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <TextView
        android:id="@+id/tv_date_call_log"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>
```

<Tabs>
  <Tab title="Kotlin">
    ```kotlin YourActivity.kt lines theme={null}
    cometchatCallLogs.setItemView(object : CallLogsViewHolderListener() {
        override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View {
            return LayoutInflater.from(context).inflate(R.layout.call_log_list_item, null)
        }

        override fun bindView(
            context: Context,
            createdView: View,
            call: CallLog,
            holder: RecyclerView.ViewHolder,
            callList: List<CallLog>,
            position: Int
        ) {
            val avatar: CometChatAvatar = createdView.findViewById(R.id.avatar)
            val name: TextView = createdView.findViewById(R.id.tv_title)
            val subTitle: TextView = createdView.findViewById(R.id.tv_subtitle)
            val date: TextView = createdView.findViewById(R.id.tv_date_call_log)

            val layoutParams = LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
            )

            createdView.layoutParams = layoutParams
            val callUser = call.initiator as CallUser
            val callUser1 = call.receiver as CallUser
            val isInitiator = callUser.uid == CometChat.getLoggedInUser().uid
            date.text = SimpleDateFormat("dd MMM, hh:mm a").format(call.initiatedAt * 1000)
            if (call.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (call
                    .status
                    == CometChatCallsConstants.CALL_STATUS_MISSED)
            ) {
                avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_missed_call, null)!!)
                subTitle.text = "Missed Call"
            } else {
                if (isInitiator) {
                    avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_outgoing_call, null)!!)
                    subTitle.text = "Outgoing Call"
                    name.text = callUser1.name
                } else {
                    avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_incoming_call, null)!!)
                    subTitle.text = "Incoming Call"
                    name.text = callUser.name
                }
            }
        }
    })
    ```
  </Tab>

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

        @Override
        public void bindView(Context context, View createdView, CallLog call, RecyclerView.ViewHolder holder, List<CallLog> callList, int position) {
            CometChatAvatar avatar = createdView.findViewById(R.id.avatar);
            TextView name = createdView.findViewById(R.id.tv_title);
            TextView subTitle = createdView.findViewById(R.id.tv_subtitle);
            TextView date = createdView.findViewById(R.id.tv_date_call_log);

            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
            );

            createdView.setLayoutParams(layoutParams);
            CallUser callUser = (CallUser) call.getInitiator();
            CallUser callUser1 = (CallUser) call.getReceiver();
            boolean isInitiator = callUser.getUid().equals(CometChat.getLoggedInUser().getUid());
            date.setText(new SimpleDateFormat("dd MMM, hh:mm a").format(call.getInitiatedAt() * 1000));
            if (call.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || call
                .getStatus()
                .equals(CometChatCallsConstants.CALL_STATUS_MISSED)) {
                avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_missed_call, null));
                subTitle.setText("Missed Call");
            } else {
                if (isInitiator) {
                    avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_outgoing_call, null));
                    subTitle.setText("Outgoing Call");
                    name.setText(callUser1.getName());
                } else {
                    avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_incoming_call, null));
                    subTitle.setText("Incoming Call");
                    name.setText(callUser.getName());
                }
            }
        }
    });
    ```
  </Tab>
</Tabs>

### `setOptions`

Replace the long-press context menu entirely.

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

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

### `setAddOptions`

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

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

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

### `setLoadingView`

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

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatCallLogs.setLoadingView(R.layout.your_loading_view)
    ```
  </Tab>

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

### `setEmptyView`

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

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatCallLogs.setEmptyView(R.layout.your_empty_view)
    ```
  </Tab>

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

### `setErrorView`

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

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatCallLogs.setErrorView(R.layout.your_error_view)
    ```
  </Tab>

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

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

## Common Patterns

### Hide all chrome — minimal list

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

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

### Missed calls only

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = CallLogRequest.CallLogRequestBuilder()
        .setCallStatus(CometChatCallsConstants.CALL_STATUS_MISSED)
    cometchatCallLogs.setCallLogRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    CallLogRequest.CallLogRequestBuilder builder = new CallLogRequest.CallLogRequestBuilder()
        .setCallStatus(CometChatCallsConstants.CALL_STATUS_MISSED);
    cometchatCallLogs.setCallLogRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

### Calls with recordings only

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = CallLogRequest.CallLogRequestBuilder()
        .setHasRecording(true)
    cometchatCallLogs.setCallLogRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    CallLogRequest.CallLogRequestBuilder builder = new CallLogRequest.CallLogRequestBuilder()
        .setHasRecording(true);
    cometchatCallLogs.setCallLogRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

### Audio calls only

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    val builder = CallLogRequest.CallLogRequestBuilder()
        .setCallType(CometChatCallsConstants.CALL_TYPE_AUDIO)
    cometchatCallLogs.setCallLogRequestBuilder(builder)
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    CallLogRequest.CallLogRequestBuilder builder = new CallLogRequest.CallLogRequestBuilder()
        .setCallType(CometChatCallsConstants.CALL_TYPE_AUDIO);
    cometchatCallLogs.setCallLogRequestBuilder(builder);
    ```
  </Tab>
</Tabs>

## Advanced Methods

### `refreshCallLogs`

Forces a refresh of the call log list, re-fetching data from the server.

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

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

### `setDateFormat`

Sets a legacy `SimpleDateFormat` for call log timestamps.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    cometchatCallLogs.setDateFormat(SimpleDateFormat("dd/MM/yyyy, HH:mm:ss", Locale.getDefault()))
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    cometchatCallLogs.setDateFormat(new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss", Locale.getDefault()));
    ```
  </Tab>
</Tabs>

### `setDateTimeFormatter`

Provides a custom implementation of `DateTimeFormatterCallback` to configure how time and date values are displayed. Each method corresponds to a specific case:

* `time(long timestamp)` — Custom full timestamp format
* `today(long timestamp)` — Called when a call log is from today
* `yesterday(long timestamp)` — Called for yesterday's call logs
* `lastWeek(long timestamp)` — Call logs from the past week
* `otherDays(long timestamp)` — Older call logs
* `minutes(long diffInMinutesFromNow, long timestamp)` — e.g., "5 minutes ago"
* `hours(long diffInHourFromNow, long timestamp)` — e.g., "2 hours ago"

<Tabs>
  <Tab title="Kotlin">
    ```kotlin lines theme={null}
    import java.text.SimpleDateFormat
    import java.util.*

    cometchatCallLogs.setDateTimeFormatter(object : DateTimeFormatterCallback {

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

        override fun time(timestamp: Long): String {
            return fullTimeFormatter.format(Date(timestamp))
        }

        override fun today(timestamp: Long): String {
            return "Today"
        }

        override fun yesterday(timestamp: Long): String {
            return "Yesterday"
        }

        override fun lastWeek(timestamp: Long): String {
            return "Last Week"
        }

        override fun otherDays(timestamp: Long): String {
            return dateFormatter.format(Date(timestamp))
        }

        override fun minutes(diffInMinutesFromNow: Long, timestamp: Long): String {
            return "$diffInMinutesFromNow mins ago"
        }

        override fun hours(diffInHourFromNow: Long, timestamp: Long): String {
            return "$diffInHourFromNow hrs ago"
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java lines theme={null}
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;

    cometchatCallLogs.setDateTimeFormatter(new DateTimeFormatterCallback() {

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

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

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

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

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

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

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

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

### Internal Access

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

| Method                        | Returns                    | Description                                     |
| ----------------------------- | -------------------------- | ----------------------------------------------- |
| `getBinding()`                | `CometchatCallLogsBinding` | The ViewBinding for the component's root layout |
| `getViewModel()`              | `CallLogsViewModel`        | The ViewModel managing call log data and state  |
| `getAdapter()`                | `CallLogsAdapter`          | The adapter powering the RecyclerView           |
| `setAdapter(CallLogsAdapter)` | `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 `CometChatCallLogsStyle` in `themes.xml`, then apply with `setStyle()`.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/xIG5VBdyNJ5cYSqE/images/d0eb378f-calls_styling-72e5f287e16313403492a56094660446.png?fit=max&auto=format&n=xIG5VBdyNJ5cYSqE&q=85&s=c9a98d867c580745a4a5dc651a2b5300" width="1280" height="800" data-path="images/d0eb378f-calls_styling-72e5f287e16313403492a56094660446.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="CustomCallLogStyle" parent="CometChatCallLogsStyle">
        <item name="cometchatCallLogsAvatarStyle">@style/CustomAvatarStyle</item>
        <item name="cometchatCallLogsSeparatorColor">#F76808</item>
        <item name="cometchatCallLogsTitleTextColor">#F76808</item>
    </style>
```

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

  <Tab title="Java">
    ```java lines theme={null}
    cometchatCallLogs.setStyle(R.style.CustomCallLogStyle);
    ```
  </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_call_logs.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            |
| `setCornerRadius`                     | `@Dimension int` | Corner radius of the component               |
| `setStrokeColor`                      | `@ColorInt int`  | Stroke color of the component border         |
| `setStrokeWidth`                      | `@Dimension int` | Stroke width of the component border         |
| `setBackIcon`                         | `Drawable`       | Custom back icon drawable                    |
| `setBackIconTint`                     | `@ColorInt int`  | Tint color for the back icon                 |
| `setTitleTextColor`                   | `@ColorInt int`  | Title text color in the toolbar              |
| `setTitleTextAppearance`              | `@StyleRes int`  | Title text appearance in the toolbar         |
| `setItemTitleTextColor`               | `@ColorInt int`  | Text color for call log item titles          |
| `setItemTitleTextAppearance`          | `@StyleRes int`  | Text appearance for call log item titles     |
| `setItemSubtitleTextColor`            | `@ColorInt int`  | Text color for call log item subtitles       |
| `setItemSubtitleTextAppearance`       | `@StyleRes int`  | Text appearance for call log item subtitles  |
| `setSeparatorColor`                   | `@ColorInt int`  | Color of list item separators                |
| `setItemIncomingCallIcon`             | `Drawable`       | Icon for incoming call indicators            |
| `setItemIncomingCallIconTint`         | `@ColorInt int`  | Tint for incoming call icon                  |
| `setItemOutgoingCallIcon`             | `Drawable`       | Icon for outgoing call indicators            |
| `setItemOutgoingCallIconTint`         | `@ColorInt int`  | Tint for outgoing call icon                  |
| `setItemMissedCallIcon`               | `Drawable`       | Icon for missed call indicators              |
| `setItemMissedCallIconTint`           | `@ColorInt int`  | Tint for missed call icon                    |
| `setItemMissedCallTitleColor`         | `@ColorInt int`  | Title text color for missed call entries     |
| `setItemAudioCallIcon`                | `Drawable`       | Icon for audio call action button            |
| `setItemAudioCallIconTint`            | `@ColorInt int`  | Tint for audio call action icon              |
| `setItemVideoCallIcon`                | `Drawable`       | Icon for video call action button            |
| `setItemVideoCallIconTint`            | `@ColorInt int`  | Tint for video call action icon              |
| `setAvatarStyle`                      | `@StyleRes int`  | Style for call log avatars                   |
| `setDateStyle`                        | `@StyleRes int`  | Style for date/time display                  |
| `setEmptyStateTitleTextAppearance`    | `@StyleRes int`  | Title text appearance for the empty state    |
| `setEmptyStateTitleTextColor`         | `@ColorInt int`  | Title text color for the empty state         |
| `setEmptyStateSubtitleTextAppearance` | `@StyleRes int`  | Subtitle text appearance for the empty state |
| `setEmptyStateSubtitleTextColor`      | `@ColorInt int`  | Subtitle text color for the empty state      |
| `setErrorTitleTextAppearance`         | `@StyleRes int`  | Title text appearance for the error state    |
| `setErrorTitleTextColor`              | `@ColorInt int`  | Title text color for the error state         |
| `setErrorSubtitleTextAppearance`      | `@StyleRes int`  | Subtitle text appearance for the error state |
| `setErrorSubtitleTextColor`           | `@ColorInt int`  | Subtitle text color for the error state      |

## Customization Matrix

| What to change                           | Where             | Property/API                                      | Example                                                       |
| ---------------------------------------- | ----------------- | ------------------------------------------------- | ------------------------------------------------------------- |
| Override behavior on user interaction    | Activity/Fragment | `setOn<Event>` callbacks                          | `setOnItemClick((v, pos, cl) -> { ... })`                     |
| Filter which call logs appear            | Activity/Fragment | `setCallLogRequestBuilder`                        | `setCallLogRequestBuilder(builder)`                           |
| Toggle visibility of UI elements         | Activity/Fragment | `set<Feature>Visibility(int)`                     | `setSeparatorVisibility(View.GONE)`                           |
| Replace a section of the list item       | Activity/Fragment | `set<Slot>View`                                   | `setLeadingView(listener)`                                    |
| Change colors, fonts, spacing            | `themes.xml`      | `CometChatCallLogsStyle`                          | `<item name="cometchatCallLogsSeparatorColor">#F76808</item>` |
| Avatar style (corner radius, background) | `themes.xml`      | `cometchatCallLogsAvatarStyle`                    | `<item name="cometchatAvatarStrokeRadius">8dp</item>`         |
| Apply a custom style                     | Activity/Fragment | `setStyle(int styleRes)`                          | `cometchatCallLogs.setStyle(R.style.CustomCallLogStyle);`     |
| Back button visibility                   | Activity/Fragment | `setBackIconVisibility(int)`                      | `.setBackIconVisibility(View.VISIBLE);`                       |
| Toolbar visibility                       | Activity/Fragment | `setToolbarVisibility(int)`                       | `.setToolbarVisibility(View.GONE);`                           |
| Title visibility                         | Activity/Fragment | `setTitleVisibility(int)`                         | `.setTitleVisibility(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);`                         |
| Date/time formatting                     | Activity/Fragment | `setDateTimeFormatter(DateTimeFormatterCallback)` | See `setDateTimeFormatter` code above                         |
| Legacy date format                       | Activity/Fragment | `setDateFormat(SimpleDateFormat)`                 | `setDateFormat(new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss"))` |
| Long-press options (replace)             | Activity/Fragment | `setOptions(Function2)`                           | See `setOptions` code above                                   |
| Long-press options (append)              | Activity/Fragment | `setAddOptions(Function2)`                        | See `setAddOptions` 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(CallLogsViewHolderListener)`      | See `setLeadingView` code above                               |
| Title view                               | Activity/Fragment | `setTitleView(CallLogsViewHolderListener)`        | See `setTitleView` code above                                 |
| Subtitle view                            | Activity/Fragment | `setSubtitleView(CallLogsViewHolderListener)`     | See `setSubtitleView` code above                              |
| Trailing view                            | Activity/Fragment | `setTrailingView(CallLogsViewHolderListener)`     | See `setTrailingView` code above                              |
| Entire list item                         | Activity/Fragment | `setItemView(CallLogsViewHolderListener)`         | See `setItemView` code above                                  |
| Call icon click listener                 | Activity/Fragment | `setOnCallIconClickListener(OnCallIconClick)`     | See `setOnCallIconClickListener` code above                   |
| Refresh call logs                        | Activity/Fragment | `refreshCallLogs()`                               | `.refreshCallLogs();`                                         |
| Internal adapter access                  | Activity/Fragment | `getAdapter()` / `setAdapter()`                   | Advanced use only                                             |

## Next Steps

<CardGroup cols={2}>
  <Card title="Call Buttons" icon="phone" href="/ui-kit/android/call-buttons">
    Voice and video call initiation buttons
  </Card>

  <Card title="Conversations" icon="comments" href="/ui-kit/android/conversations">
    Browse recent conversations
  </Card>

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

  <Card title="Incoming Call" icon="phone-arrow-down-left" href="/ui-kit/android/incoming-call">
    Incoming call notification with accept/reject
  </Card>
</CardGroup>
