Skip to content

easemob/easemob-uikit-android

Repository files navigation

Chat UIKit Readme

English | 中文

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

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

Table of contents

Product Experience

In this project, there is a best-practice demonstration project in the app folder for you to build your own business capabilities.

If you want to experience the functions of chat_uikit, you can scan the following QR code to try the demo.

Demo

Development Environment

  • Android Studio Flamingo | 2022.2.1 or later
  • Gradle 8.0 or later
  • TargetVersion 26 or later
  • Android SDK API 21 or later
  • JDK 17 or later

Installation

The UIKit can be integrated with Gradle and module source code.

Integrate with Gradle

Gradle before 7.0

Add the Maven remote repository in build.gradle or build.gradle.kts in the root directory of the project.

buildscript {
    repositories {
        ...
        mavenCentral()
    }
}
allprojects {
    repositories {
        ...
        mavenCentral()
    }
}

Gradle later than 7.0

Add the Maven remote repository in settings.gradle or settings.gradle.kts in the root directory of the project.

pluginManagement {
    repositories {
        ...
        mavenCentral()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        ...
        mavenCentral()
    }
}

Module remote dependency

Add the following dependency to build.gradle.kts of the app project:

implementation("io.hyphenate:ease-chat-kit:4.8.1")

Integrate with the Module source code

Acquire the Chat UIKit source code from the GitHub repository and integrate it in the following way:

  1. Add the following code in the settings.gradle.kts file (/Gradle Scripts/settings.gradle.kts(Project Settings)) in the root directory.
include(":chat-uikit")
project(":chat-uikit").projectDir = File("../chatuikit-android/ease-im-kit")
  1. Add the following code in build.gradle.kts (/Gradle Scripts/build.gradle(Module: app)).
//chat-uikit
implementation(project(mapOf("path" to ":chat-uikit")))

Prevent code obfuscation

Add the following lines to app/proguard-rules.pro to prevent code obfuscation.

-keep class com.hyphenate.** {*;}
-dontwarn  com.hyphenate.**

Basic project structure of chat_uikit

└── uikit
    ├── EaseIM                                   // UIKit SDK entry
    ├── EaseIMConfig                             // UIKit SDK configuration class
    ├── feature                                  // UIKit function module
    │   ├── chat                                   // Chat module
    │   │   ├── activities                            // Activity folder
    │   │   │   └── EaseChatActivity                  // Chat page built in the UIKit
    │   │   ├── adapter                               // Adapter folder of the chat module
    │   │   │   └── EaseMessagesAdapter               // Message list adapter
    │   │   ├── controllers                           // Controller of all functions of the chat module
    │   │   ├── pin                                   // Message pinning
    │   │   ├── urlpreview                            // URL preview
    │   │   ├── reply                                 // Message reply
    │   │   ├── report                                // Message reporting
    │   │   ├── chathistory                           // Chat history
    │   │   ├── forward                               // Message forwarding
    │   │   ├── reaction                              // Message reaction
    │   │   ├── search                                // Message search
    │   │   ├── translation                           // Message translation
    │   │   ├── viewholders                           // Message type ViewHolder
    │   │   ├── widgets                               // Custom view of the chat module
    │   │   └── EaseChatFragment                      // Chat fragment built in the UIKit
    │   ├── conversation                           // Conversation list module
    │   │   ├── adapter                               // Adapter folder
    │   │   │   └── EaseConversationListAdapter       // Conversation list adapter
    │   │   ├── viewholders                           // Conversation ViewHolder
    │   │   ├── widgets                               // Custom view of the conversation list module
    │   │   └── EaseConversationListFragment          // Conversation list fragment built in the UIKit
    │   ├── thread                                 // Message thread module
    │   │   ├── adapter                               // Adapter folder
    │   │   │   └── EaseChatThreadListAdapter         // Message thread list adapter
    │   │   ├── viewholder                            // Message thread ViewHolder 
    │   │   ├── widgets                               // Custom view of the message thread module
    │   │   └── EaseChatThreadActivity               // Thread chat page within the UIKit
    │   ├── contact                               // Contact list module
    │   │   ├── adapter                               // Contact list adapter folder 
    │   │   │   └── EaseContactListAdapter            // Contact list adapter
    │   │   ├── viewholders                           // Contact ViewHolder
    │   │   ├── widgets                               // Custom view of the contact list module
    │   │   └── EaseContactsListFragment              // Contact list fragment built in the UIKit
    │   └── group                                 // Group module
    │       ├── fragments                             // Group fragment
    │       ├── adapter                               // Adapter folder 
    │       │   └── EaseGroupListAdapter                // Group list adapter
    │       ├── viewholders                           // ViewHolder   Message ViewHolder
    │       └── EaseGroupListActivity                 // Group list UI built in the UIKit
    ├── repository                               // UIKit SDK data repository
    ├── viewmodel                                // UIKit SDK ViewModel
    ├── provider                                 // UIKit SDK Provider
    ├── common                                   // Public class of UIKit SDK
    ├── interfaces                               // API class of UIKit SDK
    └── widget                                   // Custom view of UIKit SDK

Permission requirements

<!-- IM SDK required start -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- IM SDK required end -->
<!-- IM UIKit required start -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Android 13 to replace READ_EXTERNAL_STORAGE permission -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<!-- Android 14 is used to grant partial access to photos and videos -->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED"/>
<!-- IM UIKit required end -->

Initialize and log in to the UIKit

Initialize the UIKit

You need to initialize the UIKit before using it:

val options = ChatOptions()
options.appKey = "[Your appkey]"
EaseIM.init(this, options)

Log in to the UIKit

val user = EaseProfile(userName, nickname, avatarUrl)
EaseIM.login(user, token
    , onSuccess = {
        // Add success logic
    }, onError = { code, error ->
        // Add error logic
    }
)

Log out of the UIKit

EaseIM.logout(unbindDeviceToken
    , onSuccess = {
        // Add success logic
    }, onError = { code, error ->
        // Add error logic
    }
)

Create pages

Create the chat page

EaseChatActivity

The UIKit provides the EaseChatActivity page. You can call the EaseChatActivity#actionStart method to create the chat page.

// conversationId: 1v1 is peer's userID, group chat is groupID
// chatType can be EaseChatType#SINGLE_CHAT, EaseChatType#GROUP_CHAT
EaseChatActivity.actionStart(mContext, conversationId, chatType)

The EaseChatActivity page requests permissions, like camera permissions and voice permissions.

EaseChatFragment

Alternatively, you can create the chat page with EaseChatFragment:

class ChatActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_chat)
        // conversationID: 1v1 is peer's userID, group chat is groupID
        // chatType can be ChatType#SINGLE_CHAT, ChatType#GROUP_CHAT
        EaseChatFragment.Builder(conversationId, chatType)
                        .build()?.let { fragment ->
                            supportFragmentManager.beginTransaction()
                                .replace(R.id.fl_fragment, fragment).commit()
                        }
    }
}

Create the conversation list page

UIKit provides EaseConversationListFragment. You can create the conversation list page by adding EaseConversationListFragment to the Activity.

class ConversationListActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_conversation_list)

        EaseConversationListFragment.Builder()
                        .build()?.let { fragment ->
                            supportFragmentManager.beginTransaction()
                                .replace(R.id.fl_fragment, fragment).commit()
                        }
    }
}

Create the contact list page

UIKit provides EaseContactsListFragment. You can create the contact list page by adding EaseContactsListFragment to the Activity.

class ContactListActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_contact_list)

        EaseContactsListFragment.Builder()
                        .build()?.let { fragment ->
                            supportFragmentManager.beginTransaction()
                                .replace(R.id.fl_fragment, fragment).commit()
                        }
    }
}

Advanced customization

Chat page

Customize with EaseChatFragment.Builder

EaseChatFragment allows you to custom settings shown below with Builder:

EaseChatFragment

// conversationID: 1v1 is peer's userID, group chat is groupID
// easeChatType: SINGLE_CHAT, GROUP_CHAT
EaseChatFragment.Builder(conversationID, easeChatType)
        .useTitleBar(true)
        .setTitleBarTitle("title")
        .setTitleBarSubTitle("subtitle")
        .enableTitleBarPressBack(true)
        .setTitleBarBackPressListener(onBackPressListener)
        .setSearchMessageId(searchMessageId)
        .getHistoryMessageFromServerOrLocal(false)
        .setOnChatExtendMenuItemClickListener(onChatExtendMenuItemClickListener)
        .setOnChatInputChangeListener(onChatInputChangeListener)
        .setOnMessageItemClickListener(onMessageItemClickListener)
        .setOnMessageSendCallback(onMessageSendCallback)
        .setOnWillSendMessageListener(willSendMessageListener)
        .setOnChatRecordTouchListener(onChatRecordTouchListener)
        .setOnMessageForwardCallback(onMessageForwardCallback)
        .setOnSendCombineMessageCallback(onSendCombineMessageCallback)
        .setOnReactionMessageListener(onReactionMessageListener)
        .setOnModifyMessageListener(onModifyMessageListener)
        .setOnReportMessageListener(onReportMessageListener)
        .setOnTranslationMessageListener(onTranslationMessageListener)
        .setMsgTimeTextColor(msgTimeTextColor)
        .setMsgTimeTextSize(msgTimeTextSize)
        .setReceivedMsgBubbleBackground(receivedMsgBubbleBackground)
        .setSentBubbleBackground(sentBubbleBackground)
        .showNickname(false)
        .hideReceiverAvatar(false)
        .hideSenderAvatar(true)
        .setChatBackground(chatBackground)
        .setChatInputMenuBackground(inputMenuBackground)
        .setChatInputMenuHint(inputMenuHint)
        .sendMessageByOriginalImage(true)
        .setThreadMessage(isChatThread)
        .setTargetTranslationList(targetTranslationList)
        .setEmptyLayout(R.layout.layout_chat_empty)
        .setCustomAdapter(customAdapter)
        .setCustomFragment(myChatFragment)
        .build()

EaseChatFragment#Builder provides the following methods:

Method Description
useTitleBar() Sets to use the default title bar (EaseTitleBar):
- true: Yes
- (Default) false: No
setTitleBarTitle() Sets the title of the title bar.
setTitleBarSubTitle() Sets the sub-title of the title bar.
enableTitleBarPressBack() Sets whether to show the back button in the title bar:
- true: Yes
- (Default) false: No
setTitleBarBackPressListener() Sets the event that occurs when clicking the the back button in the title bar.
setSearchMessageId() Sets the message ID for search. If a match is found, EaseChatFragment will display the target message as well as 10 messages following it.
getHistoryMessageFromServerOrLocal() Sets whether to preferentially get messages from the server or local storage.
setOnChatExtendMenuItemClickListener() Sets the listener for chat extension items.
setOnChatInputChangeListener() Sets the listener for text changes on the menu.
setOnMessageItemClickListener() Sets the listener for item click events, like the click and long press events of a message cell and avatar.
setOnMessageSendCallback() Sets the message sending result callback.
setOnWillSendMessageListener() Sets the listener for adding message extension attributes before sending a message.
setOnChatRecordTouchListener() Sets the recording button touch event.
setOnMessageForwardCallback() Sets the message forwarding result callback.
setOnSendCombineMessageCallback() Sets the result callback of sending a combined message.
setOnReactionMessageListener() Sets the listener for message Reaction operation result.
setOnModifyMessageListener() Sets the listener for message edit result.
setOnReportMessageListener() Sets the listener for message reporting result.
setOnTranslationMessageListener() Sets the listener for message translation result.
setMsgTimeTextColor() Sets the color of the timeline.
setMsgTimeTextSize() Sets the font size of the timeline text.
setReceivedMsgBubbleBackground() Sets the background color of the received message cell.
setSentBubbleBackground() Sets the background color of the sent message cell.
showNickname() Sets whether to display the nickname:
- true: Yes
- (Default) false: No
hideReceiverAvatar() Sets to hide the recipient avatar. By default, the recipient avatar is displayed.
hideSenderAvatar() Sets to hide the sender avatar. By default, the sender avatar is displayed.
setChatBackground() Sets the background of the chat list section.
setChatInputMenuBackground() Sets the background of the input bar.
setChatInputMenuHint() Sets the hint in the text box in the input bar.
sendMessageByOriginalImage() Sets whether to send the original image for an image message:
- true: Yes
- (Default) false: No
setThreadMessage() Sets whether to set the current conversation as a thread conversation:
- true: Yes
- (Default) false: No
setTargetTranslationList() Sets the list of target languages for translation. You need to enable the translation function before calling this method.
setEmptyLayout() Sets the empty page for the chat list.
setCustomAdapter() Sets a custom adapter. By default, EaseMessageAdapter is used.
setCustomFragment() Sets the custom chat fragment by inheriting EaseChatFragment.

Add a custom message layout

You can create a CustomMessageAdapter, CustomChatTypeViewViewHolder, and CustomTypeChatRow by inheriting EaseMessageAdapter, EaseChatRowViewHolder, and EaseChatRow, and then set CustomMessageAdapter to EaseChatFragment#Builder#setCustomAdapter.

(1) You can create a CustomMessageAdapter by inheriting EaseMessageAdapter and overwrite getViewHolder and getItemNotEmptyViewType methods.

class CustomMessageAdapter: EaseMessagesAdapter() {

    override fun getItemNotEmptyViewType(position: Int): Int {
        // Set your own itemViewType by message type.
        // To use the default message type, return super.getItemNotEmptyViewType(position).
        return CUSTOM_YOUR_MESSAGE_TYPE
    }

    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<EaseMessage> {
        // Return the ViewHolder for the returned viewType.
        // Return the custom ViewHolder or use the default super.getViewHolder(parent, viewType).
        return CUSTOM_VIEW_HOLDER()
    }
}

(2) Create a CustomTypeChatRow by inheriting EaseChatRow.

class CustomTypeChatRow(
    private val context: Context,
    private val attrs: AttributeSet? = null,
    private val defStyle: Int = 0,
    isSender: Boolean = false
): EaseChatRow(context, attrs, defStyle, isSender) {

    override fun onInflateView() {
        inflater.inflate(if (!isSender) R.layout.layout_row_received_custom_type
        else R.layout.layout_row_sent_custom_type,
            this)
    }

    override fun onSetUpView() {
        (message?.getMessage()?.body as? ChatTextMessageBody)?.let { txtBody ->
            contentView.text = txtBody.message
        }
    }
}

(3)Create a CustomChatTypeViewViewHolder by inheriting EaseChatRowViewHolder.

class CustomChatTypeViewViewHolder(
    itemView: View
): EaseChatRowViewHolder(itemView) {

    override fun onBubbleClick(message: EaseMessage?) {
        super.onBubbleClick(message)
        // Add click event
    }
}

(4)Make improvement to CustomMessageAdapter.

class CustomMessageAdapter: EaseMessagesAdapter() {

    override fun getItemNotEmptyViewType(position: Int): Int {
        // Set your own itemViewType by message type.
        mData?.get(position)?.getMessage()?.let { msg ->
            msg.getStringAttribute("type", null)?.let { type ->
                if (type == CUSTOM_TYPE) {
                    return if (msg.direct() == ChatMessageDirection.SEND) {
                        VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME
                    } else {
                        VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER
                    }
                }
            }
        }
        // If the default message type is used, return super.getItemNotEmptyViewType(position).
        return super.getItemNotEmptyViewType(position)
    }

    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<EaseMessage> {
        // Return ViewHolder for the returned viewType. 
        if (viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME || viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER) {
            CustomChatTypeViewViewHolder(
                CustomTypeChatRow(parent.context, isSender = viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME)
            )
        }
        // Return the custom ViewHolder or use the default super.getViewHolder(parent, viewType).
        return super.getViewHolder(parent, viewType)
    }

    companion object {
        private const val CUSTOM_TYPE = "custom_type"
        private const val VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME = 1000
        private const val VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER = 1001
    }
}

(5)Add CustomMessageAdapter in EaseChatFragment#Builder.

builder.setCustomAdapter(CustomMessageAdapter())

Customize settings by inheriting EaseChatFragment

Create a CustomChatFragment by inheriting EaseChatFragment and set it in EaseChatFragment#Builder.

builder.setCustomFragment(customChatFragment)

(1) Set the functions of the list control

Get the EaseChatMessageListLayout object:

val chatMessageListLayout:EaseChatMessageListLayout? = binding?.layoutChat?.chatMessageListLayout

EaseChatMessageListLayout provides the following methods:

Method Description
setViewModel() UIKit provides EaseMessageListViewModel. You can add your own data logic by inheriting IChatMessageListRequest.
setMessagesAdapter() Sets the message list adapter that is a subclass of EaseMessagesAdapter.
getMessagesAdapter() Returns the message list adapter.
addHeaderAdapter() Adds the adapter of the header adapter of the message list.
addFooterAdapter() Adds the adapter of the foot adapter of the message list.
removeAdapter() Removes a specific adapter.
addItemDecoration() Adds the decorator of the message list.
removeItemDecoration() Removes the decorator of the message list.
setAvatarDefaultSrc() Sets the default avatar of an item.
setAvatarShapeType() Sets the avatar style: default style, round, and rectangular.
showNickname() Sets whether to display the nickname of the item. Also, EaseChatFragment#Builder provides the method for this function.
setItemSenderBackground() Sets the background of the sender. Also, EaseChatFragment#Builder provides the method for this function.
setItemReceiverBackground() Sets the background of the recipient. Also, EaseChatFragment#Builder provides a method for this function.
setItemTextSize() Sets the font size of the text message.
setItemTextColor() Sets the font color of the text message.
setTimeTextSize() Sets the font size of the timeline text. Also, EaseChatFragment#Builder provides a method for this function.
setTimeTextColor() Sets the color of the timeline text. Also, EaseChatFragment#Builder provides a method for this function.
setTimeBackground() Sets the background of the timeline.
hideChatReceiveAvatar() Sets not to display the recipient's avatar. Also, EaseChatFragment#Builder provides a method for this function.
hideChatSendAvatar() Sets not to display the sender's avatar. Also, EaseChatFragment#Builder provides a method for this function.
setOnChatErrorListener() Sets the error listener for sending a message. Also, EaseChatFragment#Builder provides a method for this function.

(2)Set extension functions

val chatExtendMenu: IChatExtendMenu? = binding?.layoutChat?.chatInputMenu?.chatExtendMenu

When getting the chatExtendMenu object, you can add, remove, and order extension functions and handle click events of these functions.

IChatExtendMenu provides the following methods:

Method Description
clear() Clears all extension menu items.
setMenuOrder() Order a specific menu item.
registerMenuItem() Add a new menu item.
  • Listen for the extension item click event.

You can use EaseChatFragment#Builder#setOnChatExtendMenuItemClickListener for listening for click events of extension items, or overwrite the onChatExtendMenuItemClick method in your custom fragment.

override fun onChatExtendMenuItemClick(view: View?, itemId: Int): Boolean {
    if(itemId == CUSTOM_YOUR_EXTEND_MENU_ID) {
        // Handle your own click event logic.
        // To consume click events, you need to return `true`. 
        return true
    }
    return super.onChatExtendMenuItemClick(view, itemId)
}

(3)Set menu items upon long press.

  • Add custom menu items.
binding?.let {
    it.layoutChat.addItemMenu(menuId, menuOrder, menuTile)
}

EaseChatLayout provides the following method that can be called upon long press

Method Description
clearMenu() Clears menu items.
addItemMenu() Adds a new menu item.
findItemVisible() Sets whether a menu item is visible by itemId.
setOnMenuChangeListener() Sets a listener for click events of menu items. This listener is already set in EaseChatFragment.
  • Handle events relating to the menu. Overwrite the following method in a custom fragment:
override fun onPreMenu(helper: EaseChatMenuHelper?, message: ChatMessage?) {
    // Callback event that occurs before the menu is displayed. Here you can set whether to display menu items by using the helper object.
}

override fun onMenuItemClick(item: EaseMenuItem?, message: ChatMessage?): Boolean {
    // If you want to intercept a certain event, you need to set to return `true`.
    return false
}

override fun onDismiss() {
    // You can handle the shortcut menu hiding event here.
}

(4) Set the properties of the input menu.

  • Get the EaseChatInputMenu object.
val chatInputMenu: EaseChatInputMenu? = binding?.layoutChat?.chatInputMenu

EaseChatInputMenu provides the following methods:

Method Description
setCustomPrimaryMenu() Sets a custom menu item, via View or Fragment.
setCustomEmojiconMenu() Sets a custom emoji, via View or Fragment
setCustomExtendMenu() Sets a custom extension function, via View, Dialog, or Fragment.
setCustomTopExtendMenu() Sets a custom top layout of the menu, via View or Fragment.
hideExtendContainer() Hides the extension area, including the emoji area and extension function area.
hideInputMenu() Hides the areas except the top area of the menu.
showEmojiconMenu() Displays the emoji function area.
showExtendMenu() Displays the extension function area.
showTopExtendMenu() Displays the top extension function area.
setChatInputMenuListener() Sets the input menu listener.
chatPrimaryMenu Gets menu items.
chatEmojiMenu Gets the emoji function menu.
chatExtendMenu Gets the extension function.
chatTopExtendMenu Gets the top extension function.
  • Gets the menu item object.
val primaryMenu: IChatPrimaryMenu? = binding?.layoutChat?.chatInputMenu?.chatPrimaryMenu

IChatPrimaryMenu provides the following methods:

Method Description
onTextInsert() Inserts texts at the cursor position.
editText Gets the input box object of the menu.
setMenuBackground() Sets the background of the menu.
  • Gets the emoji menu object.
val emojiconMenu: IChatEmojiconMenu? = binding?.layoutChat?.chatInputMenu?.chatEmojiMenu

IChatEmojiconMenu provides the following methods:

Method Description
addEmojiconGroup() Adds a custom emoji group.
removeEmojiconGroup() Removes a emoji group.
setTabBarVisibility() Sets the visibility of TabBar.

Add custom emojis:

binding?.let {
    it.layoutChat.chatInputMenu?.chatEmojiMenu?.addEmojiconGroup(EmojiconExampleGroupData.getData())
}

Conversation list page

Customize settings with EaseConversationListFragment.Builder

EaseConversationListFragment allows you to customize settings shown below with Builder.

EaseConversationListFragment.Builder()
    .useTitleBar(true)
    .setTitleBarTitle("title")
    .enableTitleBarPressBack(true)
    .setTitleBarBackPressListener(onBackPressListener)
    .useSearchBar(false)
    .setItemClickListener(onItemClickListener)
    .setOnItemLongClickListener(onItemLongClickListener)
    .setOnMenuItemClickListener(onMenuItemClickListener)
    .setConversationChangeListener(conversationChangeListener)
    .setEmptyLayout(R.layout.layout_conversation_empty)
    .setCustomAdapter(customAdapter)
    .setCustomFragment(myConversationListFragment)
    .build()

EaseConversationListFragment#Builder provides the following methods:

Method Description
useTitleBar() Sets whether to use the default title bar (EaseTitleBar):
- true: Yes
-(Default) false: No
setTitleBarTitle() Sets the title of the title bar.
enableTitleBarPressBack() Sets whether to display the back button:
- true: Yes
-(Default) false: No
setTitleBarBackPressListener() Sets the listener for the click of the back button in the title bar.
setItemClickListener() Sets the item click event listener.
setOnItemLongClickListener() Sets the item long-pressing event listener.
setOnMenuItemClickListener() Sets the item click event listener.
setConversationChangeListener() Sets the conversation change listener.
setEmptyLayout() Sets a blank page.
setCustomAdapter() Sets a custom conversation list adapter by inheriting EaseConversationListAdapter.
setCustomFragment() Sets a custom chat fragment by inheriting EaseConversationListFragment.

Add a custom conversation layout

You can add a CustomConversationListAdapter by inheriting EaseConversationListAdapter and set CustomConversationListAdapter to EaseConversationListFragment#Builder#setCustomAdapter.

(1) Create a CustomConversationListAdapter by inheriting EaseConversationListAdapter, and overwrite the getViewHolder and getItemNotEmptyViewType methods.

class CustomConversationListAdapter : EaseConversationListAdapter() {
    override fun getItemNotEmptyViewType(position: Int): Int {
        // Set a custom itemViewType by message type.
        // If the default itemViewTyp is used, return super.getItemNotEmptyViewType(position).
        return CUSTOM_YOUR_CONVERSATION_TYPE
    }

    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<EaseConversation> {
        // Return the ViewHolder by reference to the returned viewType.
        // Return the custom ViewHolder or use the default super.getViewHolder(parent, viewType).
        return CUSTOM_YOUR_VIEW_HOLDER()
    }
}

(2)Add CustomConversationListAdapter in EaseConversationListFragment#Builder.

builder.setCustomAdapter(customConversationListAdapter);

Create a CustomConversationListFragment by inheriting EaseConversationListFragment

Create a CustomConversationListFragment by inheriting EaseConversationListFragment and set it to EaseConversationListFragment#Builder.

builder.setCustomFragment(customConversationListFragment);

You can gets the EaseConversationListLayout object from CustomConversationListFragment and configure custom settings.

EaseConversationListLayout provides the following methods:

Method Description
setViewModel() UIKit provides the EaseConversationListViewModel. You can inherit IConversationListRequest and then add your own data logic.
setListAdapter() Sets a custom conversation list adapter.
getListAdapter() Gets a conversation list adapter.
getItem() Gets the data at the specific position.
makeConversionRead() Sets a conversation as read.
makeConversationTop() Pins a conversation.
cancelConversationTop() Unpins a conversation.
deleteConversation() Deletes a pinned conversation.
setOnConversationChangeListener() Sets a conversation change listener. Also, EaseConversationListFragment#Builder provides a method to set the listener.
addHeaderAdapter() Adds an adapter for the header layout of the conversation list.
addFooterAdapter() Adds an adapter for the footer layout of the conversation list.
removeAdapter() Removes an adapter.
addItemDecoration() Adds a conversation list decorator.
removeItemDecoration() Removes a conversation list decorator.
setOnItemClickListener() Sets an item click listener. Also, EaseConversationListFragment#Builder provides a method to set the listener.
setOnItemLongClickListener() Sets an item long-press listener.
setItemBackGround() Sets the item background.
setItemHeight() Sets the item height.
setAvatarDefaultSrc() Sets the default item avatar.
setAvatarSize() Sets the size of the item avatar.
setAvatarShapeType() Sets the item avatar style: default ImageView style, round, and rectangular.
setAvatarRadius() Sets the border radius of the item avatar. This setting is valid only for a rectangular avatar.
setAvatarBorderWidth() Sets the width of the item avatar frame.
setAvatarBorderColor() Sets the color of the item avatar frame.
setNameTextSize() Sets the font size of the conversation item title.
setNameTextColor() Sets the text color of the conversation item title.
setMessageTextSize() Sets the font size of message texts in the conversation item.
setMessageTextColor() Sets the color of message texts in the conversation item.
setDateTextSize() Sets the font size of the conversation item date.
setDateTextColor() Sets the text color of the conversation item date.
clearMenu() Clears menu items that appear when long pressing a conversation item.
addItemMenu() Adds a menu item that appears when long pressing a conversation item.
findItemVisible() Sets whether a menu item is visible.

Contact list page

Customize settings with EaseContactsListFragment.Builder

EaseContactsListFragment allows you to customize the settings shown below with Builder:

EaseContactsListFragment.Builder()
  .useTitleBar(true)
  .setTitleBarTitle("title")
  .enableTitleBarPressBack(true)
  .setTitleBarBackPressListener(onBackPressListener)
  .useSearchBar(false)
  .setSearchType(EaseSearchType.USER)
  .setListViewType(EaseListViewType.VIEW_TYPE_LIST_CONTACT)
  .setSideBarVisible(true)
  .setDefaultMenuVisible(true)
  .setHeaderItemVisible(true)
  .setHeaderItemList(mutableListOf<EaseCustomHeaderItem>())
  .setOnHeaderItemClickListener(OnHeaderItemClickListener)
  .setOnUserListItemClickListener(OnUserListItemClickListener)
  .setOnItemLongClickListener(onItemLongClickListener)
  .setOnContactSelectedListener(OnContactSelectedListener)
  .setEmptyLayout(R.layout.layout_conversation_empty)
  .setCustomAdapter(customAdapter)
  .setCustomFragment(myContactsListFragment)
  .build()

EaseContactsListFragment#Builder provides the following methods:

Method Description
useTitleBar() Whether to use the default title bar (EaseTitleBar):
- true: Yes
- (Default) false: No
setTitleBarTitle() Sets the title in the title bar.
enableTitleBarPressBack() Sets whether to display the back button:
- true: Yes
- (Default) false: No
setTitleBarBackPressListener() Sets the listener for the click of the back button of the title bar.
useSearchBar() Sets whether to use the search bar:
- true: Yes
- (Default) false: No
setSearchType() Sets the search type EaseSearchType:
- USER
- SELECT_USER
- CONVERSATION
setListViewType() Sets the contact list type EaseListViewType
- LIST_CONTACT (contact list by default)
- LIST_SELECT_CONTACT (contact list with checkboxes)
setSideBarVisible() Sets whether to display the initial index toolbar
- (Default) true: Yes
- false: No
setDefaultMenuVisible() Sets whether to show the default menu:
- (Default) true: Yes
- false: No
setHeaderItemVisible() Sets whether to show the contact list header layout:
- true: Yes
- (Default) false: No
setHeaderItemList() Sets the data object list of the header item of the contact list.
setOnHeaderItemClickListener() Sets the click event listener for a header item of the contact list.
setOnUserListItemClickListener() Sets the contact click event listener.
setOnItemLongClickListener() Sets the contact item long-press event listener.
setOnContactSelectedListener() Sets the contact item selection event listener.
setEmptyLayout() Sets the blank page.
setCustomAdapter() Sets a custom adapter by inheriting EaseContactListAdapter.
setCustomFragment() Sets a custom chat fragment by inheriting EaseContactListFragment.

Add a custom contact layout

You can create a CustomContactListAdapter by inheriting EaseContactListAdapter and set CustomContactListAdapter in EaseContactsListFragment#Builder#setCustomAdapter.

(1) Create a CustomContactListAdapter by inheriting EaseContactListAdapter to overwrite getViewHolder and getItemNotEmptyViewType methods.

class CustomContactListAdapter : EaseContactListAdapter() {
    override fun getItemNotEmptyViewType(position: Int): Int {
        //Set a custom itemViewType by message type.
        // If the default itemViewTyp is used, return super.getItemNotEmptyViewType(position).
        return CUSTOM_YOUR_CONTACT_TYPE
    }

    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<EaseUser> {
        // Return ViewHolder by reference to the returned viewType. 
        // Return the custom ViewHolder or use the default super.getViewHolder(parent, viewType)
        return CUSTOM_YOUR_VIEW_HOLDER()
    }
}

(2) Add CustomContactListAdapter to EaseContactsListFragment#Builder.

builder.setCustomAdapter(CustomContactListAdapter)

You can get the EaseContactsListFragment object from CustomContactListFragment and configure specific custom settings.

EaseContactListLayout provides the following methods:

Method Description
setViewModel() The UIKit provides EaseContactListViewModel. You can inherit IConversationListRequest to add your own data logic.
setListAdapter() Sets a custom contact list adapter.
getListAdapter() Gets the contact list adapter.
getItem() Gets the data at a specific location.
addHeaderAdapter() Adds the header layout adapter for the contact list.
addFooterAdapter() Adds the footer layout adapter for the contact list.
removeAdapter() Removes an adapter.
addItemDecoration() Adds a contact list decorator.
removeItemDecoration() Removes a contact list decorator.
setOnItemClickListener() Sets the contact item click listener. Also, EaseContactListFragment#Builder provides the method to set the listener.
setOnItemLongClickListener() Sets the item long-pressing listener.

Global configurations

The UIKit provides global configurations which can be set during the initialization:

val avatarConfig = EaseAvatarConfig()
// Set the avatars are round shape
avatarConfig.avatarShape = EaseImageView.ShapeType.ROUND
val config = EaseIMConfig(avatarConfig = avatarConfig)
EaseIM.init(this, options, config)

EaseAvatarConfig provides the following properties:

Property Description
avatarShape The avatar style: default style, round, and rectangular.
avatarRadius The border radius of the avatar. This property is valid only for a rectangular avatar.
avatarBorderColor The color of the avatar frame.
avatarBorderWidth The width of the avatar frame.

EaseChatConfig provides the following properties:

Property Description
enableReplyMessage Whether to enable the message reply function:
- (Default) true: Yes
- false: No
enableModifyMessageAfterSent Whether to enable the message edit function:
- (Default) true: Yes
- false: No
timePeriodCanRecallMessage The message recall duration, which is 2 minutes by default.

EaseDateFormatConfig provides the following properties:

Property Description
convTodayFormat The date format of the current day on the conversation list. The default format is "HH:mm" in the English context.
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.
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.

EaseSystemMsgConfig provides the following property:

Property Description
useDefaultContactInvitedSystemMsg Whether to enable the system message function:
(Default) - true: Yes
- false: No

EaseMultiDeviceEventConfig provides the following properties:

Property Description
useDefaultMultiDeviceContactEvent Whether to enable the default multi-device contact event processing:
(Default) - true: Yes
- false: No
useDefaultMultiDeviceGroupEvent Whether to enable the default multi-device group event processing:
(Default) - true: Yes
- false: No

User information

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

Information of the current login user

During a call to the login API EaseIM.login, the user needs to pass in an EaseProfile object. This object contains the following attributes:

  • id: The user ID. This parameter is required.
  • 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 EaseIM.updateCurrentUser to update the current user's information after login.

User information providing

UIKit provides EaseIM.setUserProfileProvider to provide user information.

EaseUserProfileProvider API is as follows:

interface EaseUserProfileProvider {
    // Gets user information synchronously
    fun getUser(userId: String?): EaseProfile?

    // Gets user information asynchronously
    fun fetchUsers(userIds: List<String>, onValueSuccess: OnValueSuccess<List<EaseProfile>>)
}

This API is used as follows:

EaseIM.setUserProfileProvider(object : EaseUserProfileProvider {
    // Gets user information synchronously
    override fun getUser(userId: String?): EaseProfile? {
        return getLocalUserInfo(userId)
    }

    override fun fetchUsers(
        userIds: List<String>,
        onValueSuccess: OnValueSuccess<List<EaseProfile>>
    ) {
        fetchUserInfoFromServer(idsMap, onValueSuccess)
    }

})

Group information providing

UIKit provides the EaseIM.setGroupProfileProvider to provide the user information.

EaseGroupProfileProvider is as follows:

interface EaseGroupProfileProvider {
    // Gets user information synchronously
    fun getGroup(userId: String?): EaseGroupProfile?

    // Gets user information asynchronously
    fun fetchGroups(userIds: List<String>, onValueSuccess: OnValueSuccess<List<EaseGroupProfile>>)
}

This API is used as follows:

EaseIM.setGroupProfileProvider(object : EaseGroupProfileProvider {
    // Gets group information synchronously
    override fun getGroup(groupId: String?): EaseGroupProfile? {
      ChatClient.getInstance().groupManager().getGroup(id)?.let {
        return EaseGroupProfile(it.groupId, it.groupName, it.extension)
      }
      return null
    }

    override fun fetchGroups(
      groupIds: List<String>,
      onValueSuccess: OnValueSuccess<List<EaseGroupProfile>>
    ) {
  
    }

})

UIKit information processing logic

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

Update information cached in UIKit

As information is cached in the UIKit, the UIKit will update the cached information via the update methods if the user information is changed.

// First call EaseIM.getCache().getUser | EaseIM.getCache().getGroup to get the local cached object, and then call the update methods:
// Updates current user information  user: EaseProfile
EaseIM.updateCurrentUser(user)
// Updates user information in batches  list: List<EaseProfile>
EaseIM.updateUsersInfo(list)
// Updates group information in batches  groups: List<EaseGroupProfile>
EaseIM.updateGroupInfo(groups)

Support for dark and light themes

UIKit 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 ease_colors.xml to this folder, and then modify the basic colors in it. Under the dark theme, the corresponding colors will also be changed.