{"id":18438198,"url":"https://github.com/easemob/easemob-uikit-android","last_synced_at":"2025-04-13T21:27:09.699Z","repository":{"id":220772823,"uuid":"750718782","full_name":"easemob/easemob-uikit-android","owner":"easemob","description":null,"archived":false,"fork":false,"pushed_at":"2025-04-10T09:38:06.000Z","size":1549,"stargazers_count":2,"open_issues_count":0,"forks_count":7,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-04-10T10:51:14.214Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/easemob.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-31T07:17:23.000Z","updated_at":"2025-03-11T06:55:04.000Z","dependencies_parsed_at":"2025-03-11T07:30:29.349Z","dependency_job_id":null,"html_url":"https://github.com/easemob/easemob-uikit-android","commit_stats":null,"previous_names":["easemob/chatuikit-android","easemob/easemob-uikit-android"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easemob%2Feasemob-uikit-android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easemob%2Feasemob-uikit-android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easemob%2Feasemob-uikit-android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easemob%2Feasemob-uikit-android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/easemob","download_url":"https://codeload.github.com/easemob/easemob-uikit-android/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248784395,"owners_count":21161121,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T06:19:00.656Z","updated_at":"2025-04-13T21:27:09.663Z","avatar_url":"https://github.com/easemob.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Chat UIKit Readme\n\n_English | [中文](README.zh.md)_\n\nThis guide gives a comprehensive overview into chat_uikit. The new chat_uikit is intended to provide developers with an efficient, plug-and-play, and highly customizable UI component library, helping you build complete and elegant IM applications that can easily satisfy most instant messaging scenarios. Please download the demo to try it out.\n\nThis guide provides an overview and usage examples of the chat_uikit framework in Android development, and presents various components and functions of this UIKit, giving developers a good understanding of how chat_uikit works and how to use it efficiently.\n\n## Table of contents\n\n- [Chat UIKit Readme](#chat-uikit-readme)\n  - [Table of contents](#table-of-contents)\n  - [Product Experience](#product-experience)\n  - [Development Environment](#development-environment)\n  - [Installation](#installation)\n    - [Integrate with Gradle](#integrate-with-gradle)\n      - [Gradle before 7.0](#gradle-before-70)\n      - [Gradle later than 7.0](#gradle-later-than-70)\n    - [Module remote dependency](#module-remote-dependency)\n    - [Integrate with the Module source code](#integrate-with-the-module-source-code)\n    - [Prevent code obfuscation](#prevent-code-obfuscation)\n  - [Basic project structure of chat\\_uikit](#basic-project-structure-of-chat_uikit)\n  - [Permission requirements](#permission-requirements)\n  - [Initialize and log in to the UIKit](#initialize-and-log-in-to-the-uikit)\n    - [Initialize the UIKit](#initialize-the-uikit)\n    - [Log in to the UIKit](#log-in-to-the-uikit)\n    - [Log out of the UIKit](#log-out-of-the-uikit)\n  - [Create pages](#create-pages)\n    - [Create the chat page](#create-the-chat-page)\n      - [UIKitChatActivity](#UIKitChatActivity)\n      - [UIKitChatFragment](#UIKitChatFragment)\n    - [Create the conversation list page](#create-the-conversation-list-page)\n    - [Create the contact list page](#create-the-contact-list-page)\n  - [Advanced customization](#advanced-customization)\n    - [Chat page](#chat-page)\n      - [Customize with UIKitChatFragment.Builder](#Customize-with-UIKitChatFragmentbuilder)\n      - [Add a custom message layout](#add-a-custom-message-layout)\n      - [Customize settings by inheriting UIKitChatFragment](#customize-settings-by-inheriting-UIKitChatFragment)\n    - [Conversation list page](#conversation-list-page)\n      - [Customize settings with ChatUIKitConversationListFragment.Builder](#customize-settings-with-ChatUIKitConversationListFragmentbuilder)\n      - [Add a custom conversation layout](#add-a-custom-conversation-layout)\n      - [Create a CustomConversationListFragment by inheriting ChatUIKitConversationListFragment](#create-a-customconversationlistfragment-by-inheriting-ChatUIKitConversationListFragment)\n    - [Contact list page](#contact-list-page)\n      - [Customize settings with ChatUIKitContactsListFragment.Builder](#customize-settings-with-ChatUIKitContactsListFragmentbuilder)\n      - [Add a custom contact layout](#add-a-custom-contact-layout)\n  - [Global configurations](#global-configurations)\n  - [User information](#user-information)\n    - [Information of the current login user](#information-of-the-current-login-user)\n    - [User information providing](#user-information-providing)\n    - [Group information providing](#group-information-providing)\n    - [UIKit information processing logic](#uikit-information-processing-logic)\n    - [Update information cached in UIKit](#update-information-cached-in-uikit)\n  - [Support for dark and light themes](#support-for-dark-and-light-themes)\n\n\n## Product Experience\n\nIn this project, there is a best-practice demonstration project in the `app` folder for you to build your own business capabilities.\n\nIf you want to experience the functions of chat_uikit, you can scan the following QR code to try the demo.\n\n![Demo](./image/demo.png)\n\n## Development Environment\n\n- Android Studio Flamingo | 2022.2.1 or later\n- Gradle 8.0 or later\n- TargetVersion 26 or later\n- Android SDK API 21 or later\n- JDK 17 or later\n\n## Installation\n\nThe UIKit can be integrated with Gradle and module source code.\n\n### Integrate with Gradle\n\n#### Gradle before 7.0\n\nAdd the Maven remote repository in `build.gradle` or `build.gradle.kts` in the root directory of the project.\n\n```kotlin\nbuildscript {\n    repositories {\n        ...\n        mavenCentral()\n    }\n}\nallprojects {\n    repositories {\n        ...\n        mavenCentral()\n    }\n}\n```\n\n#### Gradle later than 7.0\n\nAdd the Maven remote repository in `settings.gradle` or `settings.gradle.kts` in the root directory of the project.\n\n```kotlin\npluginManagement {\n    repositories {\n        ...\n        mavenCentral()\n    }\n}\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        ...\n        mavenCentral()\n    }\n}\n```\n\n### Module remote dependency\n\nAdd the following dependency to `build.gradle.kts` of the app project,where `x.y.z` indicates the [latest version](https://central.sonatype.com/artifact/io.hyphenate/ease-chat-kit/versions):\n\n```kotlin\n\nimplementation(\"io.hyphenate:ease-chat-kit:x.y.z\")\n\n```\n\n### Integrate with the Module source code\n\nAcquire the Chat UIKit source code from the [GitHub repository](https://github.com/easemob/easemob-uikit-android) and integrate it in the following way:\n\n1. Add the following code in the `settings.gradle.kts` file Project/settings.gradle.kts(Project Settings) in the root directory.\n\n```kotlin\ninclude(\":chat-uikit\")\nproject(\":chat-uikit\").projectDir = File(\"../easemob-uikit-android/ease-im-kit\")\n```\n\n2. Add the following code in `build.gradle.kts` (app/build.gradle(Module: app)).\n\n```kotlin\n//chat-uikit\nimplementation(project(mapOf(\"path\" to \":chat-uikit\")))\n```\n\n### Prevent code obfuscation\n\nAdd the following lines to `app/proguard-rules.pro` to prevent code obfuscation.\n\n```kotlin\n-keep class com.hyphenate.** {*;}\n-dontwarn  com.hyphenate.**\n```\n\n## Basic project structure of chat_uikit\n\n```\n└── uikit\n    ├── ChatUIKitClient                                   // UIKit SDK entry\n    ├── ChatUIKitConfig                             // UIKit SDK configuration class\n    ├── feature                                  // UIKit function module\n    │   ├── chat                                   // Chat module\n    │   │   ├── activities                            // Activity folder\n    │   │   │   └── UIKitChatActivity                  // Chat page built in the UIKit\n    │   │   ├── adapter                               // Adapter folder of the chat module\n    │   │   │   └── ChatUIKitMessagesAdapter               // Message list adapter\n    │   │   ├── controllers                           // Controller of all functions of the chat module\n    │   │   ├── pin                                   // Message pinning\n    │   │   ├── urlpreview                            // URL preview\n    │   │   ├── reply                                 // Message reply\n    │   │   ├── report                                // Message reporting\n    │   │   ├── chathistory                           // Chat history\n    │   │   ├── forward                               // Message forwarding\n    │   │   ├── reaction                              // Message reaction\n    │   │   ├── search                                // Message search\n    │   │   ├── translation                           // Message translation\n    │   │   ├── viewholders                           // Message type ViewHolder\n    │   │   ├── widgets                               // Custom view of the chat module\n    │   │   └── UIKitChatFragment                      // Chat fragment built in the UIKit\n    │   ├── conversation                           // Conversation list module\n    │   │   ├── adapter                               // Adapter folder\n    │   │   │   └── ChatUIKitConversationListAdapter       // Conversation list adapter\n    │   │   ├── viewholders                           // Conversation ViewHolder\n    │   │   ├── widgets                               // Custom view of the conversation list module\n    │   │   └── ChatUIKitConversationListFragment          // Conversation list fragment built in the UIKit\n    │   ├── thread                                 // Message thread module\n    │   │   ├── adapter                               // Adapter folder\n    │   │   │   └── ChatUIKitThreadListAdapter         // Message thread list adapter\n    │   │   ├── viewholder                            // Message thread ViewHolder \n    │   │   ├── widgets                               // Custom view of the message thread module\n    │   │   └── ChatUIKitThreadActivity               // Thread chat page within the UIKit\n    │   ├── contact                               // Contact list module\n    │   │   ├── adapter                               // Contact list adapter folder \n    │   │   │   └── ChatUIKitContactListAdapter            // Contact list adapter\n    │   │   ├── viewholders                           // Contact ViewHolder\n    │   │   ├── widgets                               // Custom view of the contact list module\n    │   │   └── ChatUIKitContactsListFragment              // Contact list fragment built in the UIKit\n    │   └── group                                 // Group module\n    │       ├── fragments                             // Group fragment\n    │       ├── adapter                               // Adapter folder \n    │       │   └── ChatUIKitGroupListAdapter                // Group list adapter\n    │       ├── viewholders                           // ViewHolder   Message ViewHolder\n    │       └── ChatUIKitGroupListActivity                 // Group list UI built in the UIKit\n    ├── repository                               // UIKit SDK data repository\n    ├── viewmodel                                // UIKit SDK ViewModel\n    ├── provider                                 // UIKit SDK Provider\n    ├── common                                   // Public class of UIKit SDK\n    ├── interfaces                               // API class of UIKit SDK\n    └── widget                                   // Custom view of UIKit SDK\n```\n\n## Permission requirements\n\n```xml\n\u003c!-- IM SDK required start --\u003e\n\u003cuses-permission android:name=\"android.permission.INTERNET\" /\u003e\n\u003cuses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" /\u003e\n\u003cuses-permission android:name=\"android.permission.WAKE_LOCK\" /\u003e\n\u003c!-- IM SDK required end --\u003e\n\u003c!-- IM UIKit required start --\u003e\n\u003cuses-permission android:name=\"android.permission.VIBRATE\" /\u003e\n\u003cuses-permission android:name=\"android.permission.RECORD_AUDIO\" /\u003e\n\u003cuses-permission android:name=\"android.permission.CAMERA\" /\u003e\n\u003cuses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" android:maxSdkVersion=\"32\" /\u003e\n\u003c!-- Android 13 to replace READ_EXTERNAL_STORAGE permission --\u003e\n\u003cuses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\"/\u003e\n\u003cuses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\"/\u003e\n\u003c!-- Android 14 is used to grant partial access to photos and videos --\u003e\n\u003cuses-permission android:name=\"android.permission.READ_MEDIA_VISUAL_USER_SELECTED\"/\u003e\n\u003c!-- IM UIKit required end --\u003e\n```\n\n## Initialize and log in to the UIKit\n\n### Initialize the UIKit\n\nYou need to initialize the UIKit before using it:\n\n```kotlin\nval options = ChatOptions()\noptions.appKey = \"[Your appkey]\"\nChatUIKitClient.init(this, options)\n```\n### Log in to the UIKit\n\n```kotlin\nval user = ChatUIKitProfile(userName, nickname, avatarUrl)\nChatUIKitClient.login(user, token\n    , onSuccess = {\n        // Add success logic\n    }, onError = { code, error -\u003e\n        // Add error logic\n    }\n)\n```\n\n### Log out of the UIKit\n\n```kotlin\nChatUIKitClient.logout(unbindDeviceToken\n    , onSuccess = {\n        // Add success logic\n    }, onError = { code, error -\u003e\n        // Add error logic\n    }\n)\n```\n\n## Create pages\n\n### Create the chat page\n\n#### UIKitChatActivity\n\nThe UIKit provides the `UIKitChatActivity` page. You can call the `UIKitChatActivity#actionStart` method to create the chat page.\n\n```kotlin\n// conversationId: 1v1 is peer's userID, group chat is groupID\n// chatType can be ChatUIKitType#SINGLE_CHAT, ChatUIKitType#GROUP_CHAT\nUIKitChatActivity.actionStart(mContext, conversationId, chatType)\n```\n\nThe UIKitChatActivity page requests permissions, like camera permissions and voice permissions.\n\n#### UIKitChatFragment\n\nAlternatively, you can create the chat page with `UIKitChatFragment`:\n\n```kotlin\nclass ChatActivity: AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_chat)\n        // conversationID: 1v1 is peer's userID, group chat is groupID\n        // chatType can be ChatType#SINGLE_CHAT, ChatType#GROUP_CHAT\n        UIKitChatFragment.Builder(conversationId, chatType)\n                        .build()?.let { fragment -\u003e\n                            supportFragmentManager.beginTransaction()\n                                .replace(R.id.fl_fragment, fragment).commit()\n                        }\n    }\n}\n```\n\n### Create the conversation list page\n\nUIKit provides `ChatUIKitConversationListFragment`.  You can create the conversation list page by adding `ChatUIKitConversationListFragment` to the `Activity`.\n\n```kotlin\nclass ConversationListActivity: AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_conversation_list)\n\n        ChatUIKitConversationListFragment.Builder()\n                        .build()?.let { fragment -\u003e\n                            supportFragmentManager.beginTransaction()\n                                .replace(R.id.fl_fragment, fragment).commit()\n                        }\n    }\n}\n```\n\n### Create the contact list page\n\nUIKit provides `ChatUIKitContactsListFragment`. You can create the contact list page by adding `ChatUIKitContactsListFragment` to the `Activity`.\n\n```kotlin\nclass ContactListActivity: AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_contact_list)\n\n        ChatUIKitContactsListFragment.Builder()\n                        .build()?.let { fragment -\u003e\n                            supportFragmentManager.beginTransaction()\n                                .replace(R.id.fl_fragment, fragment).commit()\n                        }\n    }\n}\n```\n\n## Advanced customization\n\n### Chat page\n\n#### Customize with UIKitChatFragment.Builder\n\nUIKitChatFragment allows you to custom settings shown below with Builder:\n\nUIKitChatFragment\n\n```kotlin\n// conversationID: 1v1 is peer's userID, group chat is groupID\n// chatType: SINGLE_CHAT, GROUP_CHAT\nUIKitChatFragment.Builder(conversationID, chatType)\n        .useTitleBar(true)\n        .setTitleBarTitle(\"title\")\n        .setTitleBarSubTitle(\"subtitle\")\n        .enableTitleBarPressBack(true)\n        .setTitleBarBackPressListener(onBackPressListener)\n        .setSearchMessageId(searchMessageId)\n        .getHistoryMessageFromServerOrLocal(false)\n        .setOnChatExtendMenuItemClickListener(onChatExtendMenuItemClickListener)\n        .setOnChatInputChangeListener(onChatInputChangeListener)\n        .setOnMessageItemClickListener(onMessageItemClickListener)\n        .setOnMessageSendCallback(onMessageSendCallback)\n        .setOnWillSendMessageListener(willSendMessageListener)\n        .setOnChatRecordTouchListener(onChatRecordTouchListener)\n        .setOnMessageForwardCallback(onMessageForwardCallback)\n        .setOnSendCombineMessageCallback(onSendCombineMessageCallback)\n        .setOnReactionMessageListener(onReactionMessageListener)\n        .setOnModifyMessageListener(onModifyMessageListener)\n        .setOnReportMessageListener(onReportMessageListener)\n        .setOnTranslationMessageListener(onTranslationMessageListener)\n        .setMsgTimeTextColor(msgTimeTextColor)\n        .setMsgTimeTextSize(msgTimeTextSize)\n        .setReceivedMsgBubbleBackground(receivedMsgBubbleBackground)\n        .setSentBubbleBackground(sentBubbleBackground)\n        .showNickname(false)\n        .hideReceiverAvatar(false)\n        .hideSenderAvatar(true)\n        .setChatBackground(chatBackground)\n        .setChatInputMenuBackground(inputMenuBackground)\n        .setChatInputMenuHint(inputMenuHint)\n        .sendMessageByOriginalImage(true)\n        .setThreadMessage(isChatThread)\n        .setTargetTranslationList(targetTranslationList)\n        .setEmptyLayout(R.layout.layout_chat_empty)\n        .setCustomAdapter(customAdapter)\n        .setCustomFragment(myChatFragment)\n        .build()\n```\n\nUIKitChatFragment#Builder provides the following methods:\n\n| Method                                 | Description                                                         |\n| -------------------------------------- | ---------------------------------------------------- |\n| useTitleBar()                          | Sets to use the default title bar (ChatUIKitTitleBar):\u003cbr/\u003e - true: Yes \u003cbr/\u003e - (Default) false: No        |\n| setTitleBarTitle()                     | Sets the title of the title bar.                                       |\n| setTitleBarSubTitle()                  | Sets the sub-title of the title bar.                                       |\n| enableTitleBarPressBack()              | Sets whether to show the back button in the title bar: \u003cbr/\u003e - true: Yes \u003cbr/\u003e - (Default) false: No           |\n| setTitleBarBackPressListener()         | Sets the event that occurs when clicking the the back button in the title bar.                           |\n| setSearchMessageId()                   | Sets the message ID for search. If a match is found, UIKitChatFragment will display the target message as well as 10 messages following it.       |\n| getHistoryMessageFromServerOrLocal()   | Sets whether to preferentially get messages from the server or local storage.                           |\n| setOnChatExtendMenuItemClickListener() | Sets the listener for chat extension items.                            |\n| setOnChatInputChangeListener()         | Sets the listener for text changes on the menu.                                   |\n| setOnMessageItemClickListener()        | Sets the listener for item click events, like the click and long press events of a message cell and avatar. |\n| setOnMessageSendCallback()             | Sets the message sending result callback.                                   |\n| setOnWillSendMessageListener()         | Sets the listener for adding message extension attributes before sending a message.                      |\n| setOnChatRecordTouchListener()         | Sets the recording button touch event.                                 |\n| setOnMessageForwardCallback()          | Sets the message forwarding result callback.                                |\n| setOnSendCombineMessageCallback()      | Sets the result callback of sending a combined message.                                 |\n| setOnReactionMessageListener()         | Sets the listener for message Reaction operation result.                                |\n| setOnModifyMessageListener()           | Sets the listener for message edit result.                                 |\n| setOnReportMessageListener()           | Sets the listener for message reporting result.                                |\n| setOnTranslationMessageListener()      | Sets the listener for message translation result.                                 |\n| setMsgTimeTextColor()                  | Sets the color of the timeline.      |\n| setMsgTimeTextSize()                   | Sets the font size of the timeline text.                                 |\n| setReceivedMsgBubbleBackground()       | Sets the background color of the received message cell.                         |\n| setSentBubbleBackground()              | Sets the background color of the sent message cell.                             |\n| showNickname()                         | Sets whether to display the nickname: \u003cbr/\u003e - true: Yes \u003cbr/\u003e - (Default) false: No                                  |\n| hideReceiverAvatar()                   | Sets to hide the recipient avatar. By default, the recipient avatar is displayed.   |\n| hideSenderAvatar()                     | Sets to hide the sender avatar. By default, the sender avatar is displayed.                   |\n| setChatBackground()                    | Sets the background of the chat list section.                                     |\n| setChatInputMenuBackground()           | Sets the background of the input bar.                                        |\n| setChatInputMenuHint()                 | Sets the hint in the text box in the input bar.                           |\n| sendMessageByOriginalImage()           | Sets whether to send the original image for an image message: \u003cbr/\u003e - true: Yes \u003cbr/\u003e - (Default) false: No                   |\n| setThreadMessage()                     | Sets whether to set the current conversation as a thread conversation: \u003cbr/\u003e - true: Yes \u003cbr/\u003e - (Default) false: No                      |\n| setTargetTranslationList()             | Sets the list of target languages for translation. You need to enable the translation function before calling this method.                        |\n| setEmptyLayout()                       | Sets the empty page for the chat list.                                    |\n| setCustomAdapter()                     | Sets a custom adapter. By default, ChatUIKitMessagesAdapter is used.  |\n| setCustomFragment()                    | Sets the custom chat fragment by inheriting UIKitChatFragment.         |\n\n#### Add a custom message layout\n\nYou can create a CustomMessageAdapter, CustomChatTypeViewViewHolder, and CustomTypeChatRow by inheriting ChatUIKitMessagesAdapter, ChatUIKitRowViewHolder, and ChatUIKitRow, and then set CustomMessageAdapter to UIKitChatFragment#Builder#setCustomAdapter.\n\n(1) You can create a CustomMessageAdapter by inheriting ChatUIKitMessagesAdapter and overwrite `getViewHolder` and `getItemNotEmptyViewType` methods.\n\n```kotlin\nclass CustomMessageAdapter: ChatUIKitMessagesAdapter() {\n\n    override fun getItemNotEmptyViewType(position: Int): Int {\n        // Set your own itemViewType by message type.\n        // To use the default message type, return super.getItemNotEmptyViewType(position).\n        return CUSTOM_YOUR_MESSAGE_TYPE\n    }\n\n    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder\u003cChatMessage\u003e {\n        // Return the ViewHolder for the returned viewType.\n        // Return the custom ViewHolder or use the default super.getViewHolder(parent, viewType).\n        return CUSTOM_VIEW_HOLDER()\n    }\n}\n```\n\n(2) Create a CustomTypeChatRow by inheriting ChatUIKitRow.\n\n```kotlin\nclass CustomTypeChatRow(\n    private val context: Context,\n    private val attrs: AttributeSet? = null,\n    private val defStyle: Int = 0,\n    isSender: Boolean = false\n): ChatUIKitRow(context, attrs, defStyle, isSender) {\n\n    override fun onInflateView() {\n        inflater.inflate(if (!isSender) R.layout.layout_row_received_custom_type\n        else R.layout.layout_row_sent_custom_type,\n            this)\n    }\n\n    override fun onSetUpView() {\n        (message?.getMessage()?.body as? ChatTextMessageBody)?.let { txtBody -\u003e\n            contentView.text = txtBody.message\n        }\n    }\n}\n```\n\n（3）Create a CustomChatTypeViewViewHolder by inheriting ChatUIKitRowViewHolder.\n\n```kotlin\nclass CustomChatTypeViewViewHolder(\n    itemView: View\n): ChatUIKitRowViewHolder(itemView) {\n\n    override fun onBubbleClick(message: ChatMessage?) {\n        super.onBubbleClick(message)\n        // Add click event\n    }\n}\n```\n\n（4）Make improvement to CustomMessageAdapter.\n\n```kotlin\nclass CustomMessageAdapter: ChatUIKitMessagesAdapter() {\n\n    override fun getItemNotEmptyViewType(position: Int): Int {\n        // Set your own itemViewType by message type.\n        mData?.get(position)?.getMessage()?.let { msg -\u003e\n            msg.getStringAttribute(\"type\", null)?.let { type -\u003e\n                if (type == CUSTOM_TYPE) {\n                    return if (msg.direct() == ChatMessageDirection.SEND) {\n                        VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME\n                    } else {\n                        VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER\n                    }\n                }\n            }\n        }\n        // If the default message type is used, return super.getItemNotEmptyViewType(position).\n        return super.getItemNotEmptyViewType(position)\n    }\n\n    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder\u003cChatMessage\u003e {\n        // Return ViewHolder for the returned viewType. \n        if (viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME || viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER) {\n            CustomChatTypeViewViewHolder(\n                CustomTypeChatRow(parent.context, isSender = viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME)\n            )\n        }\n        // Return the custom ViewHolder or use the default super.getViewHolder(parent, viewType).\n        return super.getViewHolder(parent, viewType)\n    }\n\n    companion object {\n        private const val CUSTOM_TYPE = \"custom_type\"\n        private const val VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME = 1000\n        private const val VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER = 1001\n    }\n}\n```\n\n（5）Add CustomMessageAdapter in UIKitChatFragment#Builder.\n\n```kotlin\nbuilder.setCustomAdapter(CustomMessageAdapter())\n```\n\n#### Customize settings by inheriting UIKitChatFragment\n\nCreate a CustomChatFragment by inheriting UIKitChatFragment and set it in UIKitChatFragment#Builder.\n\n```kotlin\nbuilder.setCustomFragment(customChatFragment)\n```\n\n(1) Set the functions of the list control\n\nGet the `ChatUIKitMessageListLayout` object:\n\n```kotlin\nval chatMessageListLayout:ChatUIKitMessageListLayout? = binding?.layoutChat?.chatMessageListLayout\n```\n\nChatUIKitMessageListLayout provides the following methods:\n\n| Method                       | Description                                                        |\n| ------------------------------ | ---------------------------------------------------- |\n| setViewModel()              | UIKit provides ChatUIKitMessageListViewModel. You can add your own data logic by inheriting IChatMessageListRequest. |\n| setMessagesAdapter()        | Sets the message list adapter that is a subclass of ChatUIKitMessagesAdapter.    |\n| getMessagesAdapter()        | Returns the message list adapter.                                      |\n| addHeaderAdapter()          | Adds the adapter of the header adapter of the message list.     |\n| addFooterAdapter()          | Adds the adapter of the foot adapter of the message list.                                 |\n| removeAdapter()             | Removes a specific adapter.                                              |\n| addItemDecoration()         | Adds the decorator of the message list.                                     |\n| removeItemDecoration()      | Removes the decorator of the message list.                                        |\n| setAvatarDefaultSrc()       | Sets the default avatar of an item.                                        |\n| setAvatarShapeType()        | Sets the avatar style: default style, round, and rectangular.  |\n| showNickname()              | Sets whether to display the nickname of the item. Also, UIKitChatFragment#Builder provides the method for this function.  |\n| setItemSenderBackground()   | Sets the background of the sender. Also, UIKitChatFragment#Builder provides the method for this function. |\n| setItemReceiverBackground() | Sets the background of the recipient. Also, UIKitChatFragment#Builder provides a method for this function. |\n| setItemTextSize()           | Sets the font size of the text message.                                       |\n| setItemTextColor()          | Sets the font color of the text message.                                       |\n| setTimeTextSize()           | Sets the font size of the timeline text. Also, UIKitChatFragment#Builder provides a method for this function. |\n| setTimeTextColor()          | Sets the color of the timeline text. Also, UIKitChatFragment#Builder provides a method for this function. |\n| setTimeBackground()         | Sets the background of the timeline.                                             |\n| hideChatReceiveAvatar()     | Sets not to display the recipient's avatar. Also, UIKitChatFragment#Builder provides a method for this function.  |\n| hideChatSendAvatar()        | Sets not to display the sender's avatar. Also, UIKitChatFragment#Builder provides a method for this function. |\n| setOnChatErrorListener()    | Sets the error listener for sending a message. Also, UIKitChatFragment#Builder provides a method for this function. |\n\n（2）Set extension functions\n\n```kotlin\nval chatExtendMenu: IChatExtendMenu? = binding?.layoutChat?.chatInputMenu?.chatExtendMenu\n```\n\nWhen getting the chatExtendMenu object, you can add, remove, and order extension functions and handle click events of these functions.\n\nIChatExtendMenu provides the following methods:\n\n| Method                                    | Description                                                 |\n| -------------------------------------- | ---------------------------------------------------- |\n| clear()            | Clears all extension menu items.   |\n| setMenuOrder()     | Order a specific menu item.|\n| registerMenuItem() | Add a new menu item.         |\n\n- Listen for the extension item click event.\n\nYou can use UIKitChatFragment#Builder#setOnChatExtendMenuItemClickListener for listening for click events of extension items, or overwrite the onChatExtendMenuItemClick method in your custom fragment.\n\n```kotlin\noverride fun onChatExtendMenuItemClick(view: View?, itemId: Int): Boolean {\n    if(itemId == CUSTOM_YOUR_EXTEND_MENU_ID) {\n        // Handle your own click event logic.\n        // To consume click events, you need to return `true`. \n        return true\n    }\n    return super.onChatExtendMenuItemClick(view, itemId)\n}\n```\n\n（3）Set menu items upon long press.\n\n- Add custom menu items.\n\n```kotlin\nbinding?.let {\n    it.layoutChat.addItemMenu(menuId, menuOrder, menuTile)\n}\n```\n\nChatUIKitLayout provides the following method that can be called upon long press\n\n| Method                               | Description                                                        |\n| -------------------------------------- | ---------------------------------------------------- |\n| clearMenu()                         | Clears menu items.      |\n| addItemMenu()                       | Adds a new menu item.        |\n| findItemVisible()                   | Sets whether a menu item is visible by itemId.     |\n| setOnMenuChangeListener()           | Sets a listener for click events of menu items. This listener is already set in UIKitChatFragment.  |\n\n- Handle events relating to the menu.\n  Overwrite the following method in a custom fragment:\n\n```kotlin\noverride fun onPreMenu(helper: ChatUIKitChatMenuHelper?, message: ChatMessage?) {\n    // Callback event that occurs before the menu is displayed. Here you can set whether to display menu items by using the helper object.\n}\n\noverride fun onMenuItemClick(item: ChatUIKitMenuItem?, message: ChatMessage?): Boolean {\n    // If you want to intercept a certain event, you need to set to return `true`.\n    return false\n}\n\noverride fun onDismiss() {\n    // You can handle the shortcut menu hiding event here.\n}\n```\n\n(4) Set the properties of the input menu.\n\n- Get the ChatUIKitInputMenu object.\n\n```kotlin\nval chatInputMenu: ChatUIKitInputMenu? = binding?.layoutChat?.chatInputMenu\n```\n\nChatUIKitInputMenu provides the following methods:\n\n| Method                      | Description                                                        |\n| -------------------------- | ------------------------------------------------------------ |\n| setCustomPrimaryMenu()     | Sets a custom menu item, via View or Fragment.        |\n| setCustomEmojiconMenu()    | Sets a custom emoji, via View or Fragment         |\n| setCustomExtendMenu()      | Sets a custom extension function, via View, Dialog, or Fragment.|\n| setCustomTopExtendMenu()   | Sets a custom top layout of the menu, via View or Fragment. |\n| hideExtendContainer()      | Hides the extension area, including the emoji area and extension function area.   |\n| hideInputMenu()            | Hides the areas except the top area of the menu.                    |\n| showEmojiconMenu()         | Displays the emoji function area.                                          |\n| showExtendMenu()           | Displays the extension function area.                                          |\n| showTopExtendMenu()        | Displays the top extension function area.                                        |\n| setChatInputMenuListener() | Sets the input menu listener.                                           |\n| chatPrimaryMenu            | Gets menu items.                                            |\n| chatEmojiMenu              | Gets the emoji function menu.                                      |\n| chatExtendMenu             | Gets the extension function.                                           |\n| chatTopExtendMenu          | Gets the top extension function.                                          |\n\n- Gets the menu item object.\n\n```kotlin\nval primaryMenu: IChatPrimaryMenu? = binding?.layoutChat?.chatInputMenu?.chatPrimaryMenu\n```\n\nIChatPrimaryMenu provides the following methods:\n\n| Method                | Description                                      |\n| ------------------- | ----------------------------------------- |\n| onTextInsert()      | Inserts texts at the cursor position.                       |\n| editText            | Gets the input box object of the menu.     |\n| setMenuBackground() | Sets the background of the menu.                       |\n\n- Gets the emoji menu object.\n\n```kotlin\nval emojiconMenu: IChatEmojiconMenu? = binding?.layoutChat?.chatInputMenu?.chatEmojiMenu\n```\n\nIChatEmojiconMenu provides the following methods:\n\n| Method                | Description           |\n| --------------------- | ------------------ |\n| addEmojiconGroup()    | Adds a custom emoji group.     |\n| removeEmojiconGroup() | Removes a emoji group.   |\n| setTabBarVisibility() | Sets the visibility of TabBar. |\n\nAdd custom emojis:\n\n```kotlin\nbinding?.let {\n    it.layoutChat.chatInputMenu?.chatEmojiMenu?.addEmojiconGroup(EmojiconExampleGroupData.getData())\n}\n```\n\n### Conversation list page\n\n#### Customize settings with ChatUIKitConversationListFragment.Builder\n\nChatUIKitConversationListFragment allows you to customize settings shown below with Builder.\n\n```kotlin\nChatUIKitConversationListFragment.Builder()\n    .useTitleBar(true)\n    .setTitleBarTitle(\"title\")\n    .enableTitleBarPressBack(true)\n    .setTitleBarBackPressListener(onBackPressListener)\n    .useSearchBar(false)\n    .setItemClickListener(onItemClickListener)\n    .setOnItemLongClickListener(onItemLongClickListener)\n    .setOnMenuItemClickListener(onMenuItemClickListener)\n    .setConversationChangeListener(conversationChangeListener)\n    .setEmptyLayout(R.layout.layout_conversation_empty)\n    .setCustomAdapter(customAdapter)\n    .setCustomFragment(myConversationListFragment)\n    .build()\n```\n\nChatUIKitConversationListFragment#Builder provides the following methods:\n\n| Method                            | Description                                                         |\n| -------------------------------- | ------------------------------------------------------------ |\n| useTitleBar()                      | Sets whether to use the default title bar (ChatUIKitTitleBar): \u003cbr/\u003e - true: Yes\u003cbr/\u003e -(Default) false: No           |\n| setTitleBarTitle()                 | Sets the title of the title bar.                                           |\n| enableTitleBarPressBack()          | Sets whether to display the back button: \u003cbr/\u003e - true: Yes\u003cbr/\u003e -(Default) false: No |\n| setTitleBarBackPressListener()     | Sets the listener for the click of the back button in the title bar.    |\n| setItemClickListener()             | Sets the item click event listener.                                       |\n| setOnItemLongClickListener()       | Sets the item long-pressing event listener.    |\n| setOnMenuItemClickListener()       | Sets the item click event listener.    |\n| setConversationChangeListener()    | Sets the conversation change listener.    |\n| setEmptyLayout()                   | Sets a blank page.        |\n| setCustomAdapter()                 | Sets a custom conversation list adapter by inheriting ChatUIKitConversationListAdapter.   |\n| setCustomFragment()                | Sets a custom chat fragment by inheriting ChatUIKitConversationListFragment.  |\n\n#### Add a custom conversation layout\n\nYou can add a CustomConversationListAdapter by inheriting ChatUIKitConversationListAdapter and set CustomConversationListAdapter to ChatUIKitConversationListFragment#Builder#setCustomAdapter.\n\n(1) Create a CustomConversationListAdapter by inheriting ChatUIKitConversationListAdapter, and overwrite the getViewHolder and getItemNotEmptyViewType methods.\n\n```kotlin\nclass CustomConversationListAdapter : ChatUIKitConversationListAdapter() {\n    override fun getItemNotEmptyViewType(position: Int): Int {\n        // Set a custom itemViewType by message type.\n        // If the default itemViewTyp is used, return super.getItemNotEmptyViewType(position).\n        return CUSTOM_YOUR_CONVERSATION_TYPE\n    }\n\n    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder\u003cChatUIKitConversation\u003e {\n        // Return the ViewHolder by reference to the returned viewType.\n        // Return the custom ViewHolder or use the default super.getViewHolder(parent, viewType).\n        return CUSTOM_YOUR_VIEW_HOLDER()\n    }\n}\n```\n\n（2）Add CustomConversationListAdapter in ChatUIKitConversationListFragment#Builder.\n\n```kotlin\nbuilder.setCustomAdapter(customConversationListAdapter);\n```\n\n#### Create a CustomConversationListFragment by inheriting ChatUIKitConversationListFragment\n\nCreate a CustomConversationListFragment by inheriting ChatUIKitConversationListFragment and set it to ChatUIKitConversationListFragment#Builder.\n\n```kotlin\nbuilder.setCustomFragment(customConversationListFragment);\n```\n\nYou can gets the ChatUIKitConversationListLayout object from CustomConversationListFragment and configure custom settings.\n\nChatUIKitConversationListLayout provides the following methods:\n\n| Method                                   | Description                                                            |\n| -------------------------------------- | ---------------------------------------------------------------- |\n| setViewModel()                    | UIKit provides the ChatUIKitConversationListViewModel. You can inherit IConversationListRequest and then add your own data logic. |\n| setListAdapter()                  | Sets a custom conversation list adapter.    |\n| getListAdapter()                  | Gets a conversation list adapter.     |\n| getItem()                         | Gets the data at the specific position.     |\n| makeConversionRead()              | Sets a conversation as read.     |\n| makeConversationTop()             | Pins a conversation.  |\n| cancelConversationTop()           | Unpins a conversation.  |\n| deleteConversation()              | Deletes a pinned conversation.                                          |\n| setOnConversationChangeListener() | Sets a conversation change listener. Also, ChatUIKitConversationListFragment#Builder provides a method to set the listener. |\n| addHeaderAdapter()                | Adds an adapter for the header layout of the conversation list.     |\n| addFooterAdapter()                | Adds an adapter for the footer layout of the conversation list.     |\n| removeAdapter()                   | Removes an adapter.                                              |\n| addItemDecoration()               | Adds a conversation list decorator.                                       |\n| removeItemDecoration()            | Removes a conversation list decorator.                                         |\n| setOnItemClickListener()          | Sets an item click listener. Also, ChatUIKitConversationListFragment#Builder provides a method to set the listener. |\n| setOnItemLongClickListener()      | Sets an item long-press listener.                                   |\n| setItemBackGround()               | Sets the item background.                                               |\n| setItemHeight()                   | Sets the item height.                                               |\n| setAvatarDefaultSrc()             | Sets the default item avatar.                                         |\n| setAvatarSize()                   | Sets the size of the item avatar.                                           |\n| setAvatarShapeType()              | Sets the item avatar style: default ImageView style, round, and rectangular.  |\n| setAvatarRadius()                 | Sets the border radius of the item avatar. This setting is valid only for a rectangular avatar.    |\n| setAvatarBorderWidth()            | Sets the width of the item avatar frame.                                     |\n| setAvatarBorderColor()            | Sets the color of the item avatar frame.                                     |\n| setNameTextSize()                 | Sets the font size of the conversation item title.                                   |\n| setNameTextColor()                | Sets the text color of the conversation item title.                                  |\n| setMessageTextSize()              | Sets the font size of message texts in the conversation item.                                  |\n| setMessageTextColor()             | Sets the color of message texts in the conversation item.                                  |\n| setDateTextSize()                 | Sets the font size of the conversation item date.                                 |\n| setDateTextColor()                | Sets the text color of the conversation item date.                                  |\n| clearMenu()                       | Clears menu items that appear when long pressing a conversation item. |\n| addItemMenu()                     | Adds a menu item that appears when long pressing a conversation item.     |\n| findItemVisible()                 | Sets whether a menu item is visible.  |\n\n### Contact list page\n\n#### Customize settings with ChatUIKitContactsListFragment.Builder\n\nChatUIKitContactsListFragment allows you to customize the settings shown below with Builder:\n\n```kotlin\nChatUIKitContactsListFragment.Builder()\n  .useTitleBar(true)\n  .setTitleBarTitle(\"title\")\n  .enableTitleBarPressBack(true)\n  .setTitleBarBackPressListener(onBackPressListener)\n  .useSearchBar(false)\n  .setSearchType(ChatUIKitSearchType.USER)\n  .setListViewType(ChatUIKitListViewType.VIEW_TYPE_LIST_CONTACT)\n  .setSideBarVisible(true)\n  .setDefaultMenuVisible(true)\n  .setHeaderItemVisible(true)\n  .setHeaderItemList(mutableListOf\u003cChatUIKitCustomHeaderItem\u003e())\n  .setOnHeaderItemClickListener(OnHeaderItemClickListener)\n  .setOnUserListItemClickListener(OnUserListItemClickListener)\n  .setOnItemLongClickListener(onItemLongClickListener)\n  .setOnContactSelectedListener(OnContactSelectedListener)\n  .setEmptyLayout(R.layout.layout_conversation_empty)\n  .setCustomAdapter(customAdapter)\n  .setCustomFragment(myContactsListFragment)\n  .build()\n```\n\nChatUIKitContactsListFragment#Builder provides the following methods:\n\n| Method                              | Description                                                                                                  |\n|----------------------------------|------------------------------------------------------------------------------------------------------|\n| useTitleBar()                    | Whether to use the default title bar (ChatUIKitTitleBar): \u003cbr/\u003e - true: Yes \u003cbr/\u003e - (Default) false: No                                 |\n| setTitleBarTitle()               | Sets the title in the title bar.   |\n| enableTitleBarPressBack()        | Sets whether to display the back button: \u003cbr/\u003e - true: Yes \u003cbr/\u003e - (Default) false: No                                     |\n| setTitleBarBackPressListener()   | Sets the listener for the click of the back button of the title bar.     |\n| useSearchBar()                   | Sets whether to use the search bar: \u003cbr/\u003e - true: Yes \u003cbr/\u003e - (Default) false: No                                            |\n| setSearchType()                  | Sets the search type ChatUIKitSearchType: \u003cbr/\u003e - USER  \u003cbr/\u003e - SELECT_USER \u003cbr/\u003e - CONVERSATION                      |\n| setListViewType()                | Sets the contact list type ChatUIKitListViewType \u003cbr/\u003e - LIST_CONTACT (contact list by default) \u003cbr/\u003e - LIST_SELECT_CONTACT (contact list with checkboxes) |\n| setSideBarVisible()              | Sets whether to display the initial index toolbar \u003cbr/\u003e - (Default) true: Yes \u003cbr/\u003e - false: No                                   |\n| setDefaultMenuVisible()          | Sets whether to show the default menu: \u003cbr/\u003e - (Default) true: Yes  \u003cbr/\u003e - false: No                                            |\n| setHeaderItemVisible()           | Sets whether to show the contact list header layout: \u003cbr/\u003e - true: Yes  \u003cbr/\u003e - (Default) false: No                                 |\n| setHeaderItemList()              | Sets the data object list of the header item of the contact list.     |\n| setOnHeaderItemClickListener()   | Sets the click event listener for a header item of the contact list.      |\n| setOnUserListItemClickListener() | Sets the contact click event listener.     |\n| setOnItemLongClickListener()     | Sets the contact item long-press event listener.  |\n| setOnContactSelectedListener()   | Sets the contact item selection event listener.   |\n| setEmptyLayout()                 | Sets the blank page.    |\n| setCustomAdapter()               | Sets a custom adapter by inheriting ChatUIKitContactListAdapter.     |\n| setCustomFragment()              | Sets a custom chat fragment by inheriting ChatUIKitContactsListFragment.       |\n\n#### Add a custom contact layout\n\nYou can create a CustomContactListAdapter by inheriting ChatUIKitContactListAdapter and set CustomContactListAdapter in  ChatUIKitContactsListFragment#Builder#setCustomAdapter.\n\n(1) Create a CustomContactListAdapter by inheriting ChatUIKitContactListAdapter to overwrite getViewHolder and getItemNotEmptyViewType methods.\n\n```kotlin\nclass CustomContactListAdapter : ChatUIKitContactListAdapter() {\n    override fun getItemNotEmptyViewType(position: Int): Int {\n        //Set a custom itemViewType by message type.\n        // If the default itemViewTyp is used, return super.getItemNotEmptyViewType(position).\n        return CUSTOM_YOUR_CONTACT_TYPE\n    }\n\n    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder\u003cChatUIKitUser\u003e {\n        // Return ViewHolder by reference to the returned viewType. \n        // Return the custom ViewHolder or use the default super.getViewHolder(parent, viewType)\n        return CUSTOM_YOUR_VIEW_HOLDER()\n    }\n}\n```\n\n(2) Add CustomContactListAdapter to ChatUIKitContactsListFragment#Builder.\n\n```kotlin\nbuilder.setCustomAdapter(CustomContactListAdapter)\n```\n\nYou can get the ChatUIKitContactsListFragment object from CustomContactListFragment and configure specific custom settings.\n\nChatUIKitContactListLayout provides the following methods:\n\n| Method                                  | Description                                                           |\n| -------------------------------------- | ---------------------------------------------------------------- |\n| setViewModel()                    | The UIKit provides ChatUIKitContactListViewModel. You can inherit IConversationListRequest to add your own data logic. |\n| setListAdapter()                  | Sets a custom contact list adapter.                                    |\n| getListAdapter()                  | Gets the contact list adapter.                                         |\n| getItem()                         | Gets the data at a specific location.      |\n| addHeaderAdapter()                | Adds the header layout adapter for the contact list.    |\n| addFooterAdapter()                | Adds the footer layout adapter for the contact list.   |\n| removeAdapter()                   | Removes an adapter.                                            |\n| addItemDecoration()               | Adds a contact list decorator.                                        |\n| removeItemDecoration()            | Removes a contact list decorator.                                       |\n| setOnItemClickListener()          | Sets the contact item click listener. Also, ChatUIKitContactsListFragment#Builder provides the method to set the listener. |\n| setOnItemLongClickListener()      | Sets the item long-pressing listener.                                  |\n\n## Global configurations\n\nThe UIKit provides global configurations which can be set during the initialization:\n\n```kotlin\nval avatarConfig = ChatUIKitAvatarConfig()\n// Set the avatars are round shape\navatarConfig.avatarShape = ChatUIKitImageView.ShapeType.ROUND\nval config = ChatUIKitConfig(avatarConfig = avatarConfig)\nChatUIKitClient.init(this, options, config)\n```\n\nChatUIKitAvatarConfig provides the following properties:\n\n| Property                                  | Description                                                             |\n| -------------------------------------- | ---------------------------------------------------------------- |\n| avatarShape                            | The avatar style: default style, round, and rectangular.                    |\n| avatarRadius                           | The border radius of the avatar. This property is valid only for a rectangular avatar.                           |\n| avatarBorderColor                      | The color of the avatar frame.                                                   |\n| avatarBorderWidth                      | The width of the avatar frame.                                                   |\n\n\nChatUIKitConfig provides the following properties:\n\n| Property                                  | Description                                                          |\n| -------------------------------------- | ---------------------------------------------------------------- |\n| enableReplyMessage                     | Whether to enable the message reply function: \u003cbr/\u003e - (Default) true： Yes  \u003cbr/\u003e - false： No  |\n| enableModifyMessageAfterSent           | Whether to enable the message edit function: \u003cbr/\u003e - (Default) true： Yes  \u003cbr/\u003e - false： No   |\n| timePeriodCanRecallMessage             | The message recall duration, which is 2 minutes by default. |\n\n\nChatUIKitDateFormatConfig provides the following properties:\n\n| Property                                 | Description                                                            |\n| -------------------------------------- | ---------------------------------------------------------------- |\n| convTodayFormat                       | The date format of the current day on the conversation list. The default format is \"HH:mm\" in the English context.    |\n| convOtherDayFormat                    | The date format of other dates than of the current day on the conversation list. The default format is \"HH:mm\" in the English context.   |\n| convOtherYearFormat                   | The date format of other years than this year on the conversation list. The default format is \"MMM dd, yyyy\" in the English context.    |\n\n\nChatUIKitSystemMsgConfig provides the following property:\n\n| Property                                    | Description                                                           |\n| -------------------------------------- | ---------------------------------------------------------------- |\n| useDefaultContactInvitedSystemMsg      | Whether to enable the system message function: \u003cbr/\u003e (Default) - true： Yes  \u003cbr/\u003e - false： No                                        |\n\n\nChatUIKitMultiDeviceEventConfig provides the following properties:\n\n| Property                                    | Description            |\n|--------------------------------------|-------------------|\n| useDefaultMultiDeviceContactEvent    | Whether to enable the default multi-device contact event processing：\u003cbr/\u003e (Default) - true： Yes  \u003cbr/\u003e - false： No |\n| useDefaultMultiDeviceGroupEvent      | Whether to enable the default multi-device group event processing：\u003cbr/\u003e (Default) - true： Yes  \u003cbr/\u003e - false： No|\n\n## User information\n\nUser information is used in many places in UIKit and needs to be provided by developers. This section describes how developers provide user information to UIKit.\n\n### Information of the current login user\n\nDuring a call to the login API `ChatUIKitClient.login`, the user needs to pass in an `ChatUIKitProfile` object. This object contains the following attributes:\n- `id`: The user ID. This parameter is required.\n- `name` and `avatar`: Used to display the nickname and avatar of the current user. When sending a message, you can set the two parameters to the `ext` field of the message to allow other users to present the two parameters. If you fail to pass in the two parameters during login, you can call `ChatUIKitClient.updateCurrentUser` to update the current user's information after login.\n\n### User information providing\n\nUIKit provides `ChatUIKitClient.setUserProfileProvider` to provide user information.\n\n`ChatUIKitUserProfileProvider` API is as follows:\n\n```kotlin\ninterface ChatUIKitUserProfileProvider {\n    // Gets user information synchronously\n    fun getUser(userId: String?): ChatUIKitProfile?\n\n    // Gets user information asynchronously\n    fun fetchUsers(userIds: List\u003cString\u003e, onValueSuccess: OnValueSuccess\u003cList\u003cChatUIKitProfile\u003e\u003e)\n}\n```\n\nThis API is used as follows:\n\n```kotlin\nChatUIKitClient.setUserProfileProvider(object : ChatUIKitUserProfileProvider {\n    // Gets user information synchronously\n    override fun getUser(userId: String?): ChatUIKitProfile? {\n        return getLocalUserInfo(userId)\n    }\n\n    override fun fetchUsers(\n        userIds: List\u003cString\u003e,\n        onValueSuccess: OnValueSuccess\u003cList\u003cChatUIKitProfile\u003e\u003e\n    ) {\n        fetchUserInfoFromServer(idsMap, onValueSuccess)\n    }\n\n})\n\n```\n\n### Group information providing\n\nUIKit provides the `ChatUIKitClient.setGroupProfileProvider` to provide the user information.\n\n`ChatUIKitGroupProfileProvider` is as follows:\n\n```kotlin\ninterface ChatUIKitGroupProfileProvider {\n    // Gets user information synchronously\n    fun getGroup(userId: String?): ChatUIKitGroupProfile?\n\n    // Gets user information asynchronously\n    fun fetchGroups(userIds: List\u003cString\u003e, onValueSuccess: OnValueSuccess\u003cList\u003cChatUIKitGroupProfile\u003e\u003e)\n}\n```\n\nThis API is used as follows:\n\n```kotlin\nChatUIKitClient.setGroupProfileProvider(object : ChatUIKitGroupProfileProvider {\n    // Gets group information synchronously\n    override fun getGroup(groupId: String?): ChatUIKitGroupProfile? {\n      ChatClient.getInstance().groupManager().getGroup(id)?.let {\n        return ChatUIKitGroupProfile(it.groupId, it.groupName, it.extension)\n      }\n      return null\n    }\n\n    override fun fetchGroups(\n      groupIds: List\u003cString\u003e,\n      onValueSuccess: OnValueSuccess\u003cList\u003cChatUIKitGroupProfile\u003e\u003e\n    ) {\n  \n    }\n\n})\n\n```\n\n### UIKit information processing logic\n\n- Step 1: If the information has been cached in the memory, when information needs to be presented on pages, the UIKit will first retrieve the cached data from the memory and render the page. If no information is cached, proceed to step 2.\n- Step 2. UIKit calls the provider synchronization method to obtain information locally from the application. Developers can obtain and provide the related information from the application's local database or memory. After the information is obtained, UIKit renders the page, while caching the information.\n- Step 3. If the data obtained by the synchronization method is empty, when the list page stops sliding, UIKit will return the information required for the items visible on the current page through the asynchronous method provided by the provider after excluding cache and data provided by the synchronization method. After obtaining the corresponding information from the server, the developer provides it to UIKit through `onValueSuccess`. The UIKit refreshes the list and updates the corresponding data when receiving the data.\n\n### Update information cached in UIKit\n\nAs information is cached in the UIKit, the UIKit will update the cached information via the `update` methods if the user information is changed.\n\n```kotlin\n// First call ChatUIKitClient.getCache().getUser ｜ ChatUIKitClient.getCache().getGroup to get the local cached object, and then call the update methods:\n// Updates current user information  user: ChatUIKitProfile\nChatUIKitClient.updateCurrentUser(user)\n// Updates user information in batches  list: List\u003cChatUIKitProfile\u003e\nChatUIKitClient.updateUsersInfo(list)\n// Updates group information in batches  groups: List\u003cChatUIKitGroupProfile\u003e\nChatUIKitClient.updateGroupInfo(groups)\n```\n\n## Support for dark and light themes\n\nUIKit supports both light and dark themes, with the theme colors changing with the system theme. To adjust the theme colors, you can create a new `values-night` folder in the app module, copy `uikit_colors.xml` to this folder, and then modify the basic colors in it. Under the dark theme, the corresponding colors will also be changed.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feasemob%2Feasemob-uikit-android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feasemob%2Feasemob-uikit-android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feasemob%2Feasemob-uikit-android/lists"}