会话列表页面
会话列表页面展示了当前用户设备上的所有会话。一旦 SDK 的本地消息数据库生成消息,SDK 就会生成会话列表,并按照时间倒序排列,置顶会话会排在最前。
Global IM UIKit 提供基于 Activity 类和基于 Fragment 类实现的会话列表页面。
- 基于 Activity:Global IM UIKit 默认提供的会话列表
ChatListActivity
。在 SDK 内部页面需要跳转到会话列表时,将跳转到默认的会话列表 Activity。 - 基于 Fragment:您可以在应用 Activity 中集成 Global IM UIKit 提供的会话列表
ChatListFragment
,即自定义会话列表 Activity。注意,您需要将自定义会话列表 Activity 注册到 Global IM UIKit SDK 中,以替换 Global IM UIKit 默认的会话列表 Activity。
会话列表界面
会话列表界面一般由两个部分组成:导航栏和会话列表。
会话列表页面结构
- ChatListActivity:给
ChatListFragment
提供装载容器,没有具体实现。 - ChatListFragment:绑定
ViewModel
以及页面中的各个组件 Component
,并给组件提供数据源的能力。 - ChatListModule:负责
ChatListFragment
UI 展示,并初始化当前页面的各个组件
。 - ChatListViewModel:提供会话列表页面的数据源以及所有操作的接口。
会话列表页面组件
- HeaderComponent:导航组件,提供了
连接状态提示
的显示以及搜索入口
按钮。 - HeaderSelectComponent:多选模式组件,长按选择会话时触发多选模式,Global IM UIKit 默认已实现了
会话免打扰
、会话已读
、置顶会话
和删除会话
的功能。 - ChatListComponent:会话列表组件,按时间倒序显示所有会话的列表,置顶会话会排在最前。长按会话列表中的会话时会默认触发
多选模式
以及选中当前会话
。 会话列表的每个项目的视图是在BaseChatListItemProvider.java
和创建和自定义的。 - PageStatusComponent:页面状态组件,当前会话列表没有数据时显示。
页面效果展示
如果在控制台开启了多设备消息同步功能,在 换新设备登录 或 应用卸载重装 场景下,离线补偿机制仅可获取到最近(默认离线补偿天数为 1 天,最大 7 天)的单聊、群聊会话消息。早于该天数的会话无法通过离线补偿机制获取。因此,离线补偿后的会话列表可能与原设备上或卸载前的会话列表并不一致(您可能会有丢失部分会话的错觉)。
用法
Global IM UIKit 提供了 Activity 和 Fragment 来创建会话列表页面。ChatListActivity
是默认提供的会话列表页面。您可以根据需要,选择直接使用默认的会话列表页面 Activity,也可以选择继承 ChatListActivity
或者使用 ChatListFragment
构建自定义会话列表 Activity。
Global IM UIKit 默认已经实现在会话列表页点击某条会话时,跳转到对应的会话页面。
启动会话列表页面
启动会话列表 Activity 有两种启动方式:通过调用 SDK 内置的 Activity 路由器启动,或通过 intent 跳转。您也可以自定义会话列表页的启动方式,实现从应用的其它 Activity 启动会话列表页面。
使用 RouteUtil
RouteUtil
是 Global IM UIKit 内置的 Activity 路由器,封装了 SDK 内部各页面跳转方法,可避免应用程序进行重复的 intent 封装。
如果您构建了自定义的会话列表 Activity,必须先向
RouteUtil
注册自定义 Activity,才能通过这种方式跳转到自定义会话列表 Activity,否则跳转的是 SDK 默认的ChatListActivity
。
跳转到会话列表 Activity:
RouteUtil.routeToChatListActivity(context);
通过 intent 跳转
您可以自己组装 Intent, 使用 Android 默认机制进行跳转。
Intent intent = new Intent(context, MyChatListActivity.class);
context.startActivity(intent);
继承默认会话页面 Activity
您可以通过继承 ChatListActivity
创建自定义会话列表 Activity,实现对会话列表页面的调整。注意,必须向 RouteUtil
注册自定义的会话列表 Activity。注册之后,当 SDK 需要跳转到会话列表时,会跳转到您注册的自定义会话列表 Activity。注册方法在应用生命周期内、主进程中调用一次即可。
RouteUtil.registerActivity(RouteUtil.ActivityType.CHAT_LIST_ACTIVITY, MyChatListActivity.class);
使用 自定义 ChatListFragment 构建自定义会话列表
Global IM UIKit 提供的会话列表 Fragment 类名为 ChatListFragment
。为方便应用程序自定义会话列表页面,推 荐继承使用会话列表 ChatListFragment
类,构建自定义的会话列表 Activity。通过重写工厂方法的方式
-
您需要首先通过继承
KitFragmentFactory
来重写您希望自定义的Fragment的方法。请参阅下面的代码作为示例。public class CustomFragmentFactory extends KitFragmentFactory {
@NonNull
@Override
public Fragment newChatListFragment(@NonNull Bundle args) {
return new ChatListFragment.Builder()
.withArguments(args)
.setCustomFragment(new CustomChatListFragment())
.build();
}
} -
将自定义的 KitFragmentFactory 在 Application ConfigCenter.setKitFragmentFactory(KitFragmentFactory) 替换。
public class CustomApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ConfigCenter.setKitFragmentFactory(new CustomFragmentFactory());
}
}
定制化
会话页面列表中部分样式与行为受 Global IM UIKit 全局配置影响。如需了解全局配置,参见 [配置指南]。
修改导航栏样式及功能
Global IM UIKit 支持对组件进行定制化操作,比如在导航栏栏右侧区域新增一个图标以及点击事件。通过 Global IM UIKit 的 ChatListHeaderComponent
提供增、删View的方法。
public class CustomChatListFragment extends ChatListFragment {
@Override
protected void onBindHeaderComponent(@NonNull ChatListModule module, @NonNull ChatListHeaderComponent headerComponent, @NonNull ChatListViewModel viewModel) {
super.onBindHeaderComponent(module, headerComponent, viewModel);
// 导航栏左侧-增加指定位置的View
module.getHeaderComponent().addLeftView(new View(getContext()), 0);
// 导航栏左侧-移除指定位置的View
module.getHeaderComponent().removeLeftView(0);
// 导航栏中部-增加指定位置的View
module.getHeaderComponent().addCenterView(new View(getContext()), 0);
// 导航栏中部-移除指定位置的View
module.getHeaderComponent().removeCenterView(0);
// 导航栏右侧-增加指定位置的View
module.getHeaderComponent().addRightView(new View(getContext()), 0);
// 导航栏右侧-移除指定位置的View
module.getHeaderComponent().removeRightView(0);
}
}
多选模式组件新增和移除操作项
该组件支持对操作项进行新增或者移除。
-
继承 Global IM UIKit 的
ChatListHeaderSelectComponent
创建子类
,例如CustomChatListHeaderSelectComponent
。public class CustomChatListHeaderSelectComponent extends ChatListHeaderSelectComponent {
public CustomChatListHeaderSelectComponent(@NonNull Context context) {
super(context);
}
public CustomChatListHeaderSelectComponent(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@NonNull
@Override
protected List<ChatAction<List<Conversation>>> beforeCreateChatActionView(@NonNull List<ChatAction<List<Conversation>>> chatActions) {
// 在导航栏中添加一个操作项放到下标为 0 的位置
chatActions.add(0, new ChatAction<List<Conversation>>() {
@Override
public String obtainTitle(@NonNull Context context, List<Conversation> data) {
return "Item Name";
}
@Override
public Drawable obtainDrawable(@NonNull Context context, List<Conversation> data) {
return ResourcesCompat.getDrawable(context.getResources(), io.rong.uikit.R.drawable.ic_drawable, null);
}
@Override
public void onClick(@NonNull List<Conversation> data) {
Toast.makeText(getContext(), "Clicked", Toast.LENGTH_SHORT).show();
}
});
// 添加一个操作项放到更多窗口中
chatActions.add(new ChatAction<List<Conversation>>() {
@Override
public String obtainTitle(@NonNull Context context, List<Conversation> data) {
return "Item Name";
}
@Override
public Drawable obtainDrawable(@NonNull Context context, List<Conversation> data) {
return ResourcesCompat.getDrawable(context.getResources(), io.rong.uikit.R.drawable.ic_drawable, null);
}
@Override
public void onClick(@NonNull List<Conversation> data) {
Toast.makeText(getContext(), "Clicked", Toast.LENGTH_SHORT).show();
}
// 是否添加到更多窗口中
@Override
public boolean isLocationMoreWindow() {
return true;
}
});
return chatActions;
}
} -
复制
IMKit
的rc_chat_list_module.xml
至主项目
的res/layout
中,找到<com.rongcloud.im.uikit.chatlist.component.ChatListHeaderSelectComponent />
并替换为子类全路径<com.rongcloud.im.uikit.custom.component.CustomChatListHeaderSelectComponent />
。更改前:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.rongcloud.im.uikit.chatlist.component.ChatListHeaderSelectComponent
android:id="@+id/rc_header_select_component"
android:layout_width="match_parent"
android:layout_height="match_parent" />
// 其他组件xx
</FrameLayout>更改后:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
// 只替换自定义的组件,其他的组件需要保留 (注意:不要修改组件的 android:id)
<com.rongcloud.im.uikit.custom.component.CustomChatListHeaderSelectComponent
android:id="@+id/rc_header_select_component"
android:layout_width="match_parent"
android:layout_height="match_parent" />
// 其他组件xx
</FrameLayout>
修改会话列表头像形状
会话列表中的每个会话项目上均会显示一个头像图标,即会话头像(不是聊天页面内中消息列表中的头像)。单聊会话显示对方用户头像,群聊会话显示群组头像,聚合会话显示默认头像或应用程序主动设置的头像。Global IM UIKit 支持通过 Global IM UIKit 全局配置单独控制会话列表中的会话头像样式。
会话头像显示默认为圆形 ,可修改为矩形。头像显示大小默认值为 58dp*58dp
。请在 App 初始化之后
调用以下代码进行设置:
ConfigCenter.getFeatureConfig().setKitImageEngine(new GlideKitImageEngine() {
@Override
public void loadChatListPortrait(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, Conversation conversation) {
Glide.with(context).load(url)
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
.into(imageView);
}
});
如需修改聊天页面内消息上显示的头像样式,请转至会话页面。
添加自定义空布局
Global IM UIKit 的 ChatListModule
支持在会话列表页中自定义空(Empty)视图。
- 方式一:复制
IMKit
的rc_page_status_component.xml
至主项目
的res/layout
中,并实现自己的 UI 视图。 - 方式二:继承 Global IM UIKit 的
PageStatusComponent
创建子类,重写onCreateView
实现自己的 UI 视图,并在rc_chat_list_module.xml
中把原有的组件替换为自定义组件。
是否展示网络连接状态提示
当连接断开或者重连时,SDK 会在会话列表页面与会话页面顶部展示连接状态提示栏。
如果需要在会话列表页面上禁用该提示,请在 App 初始化之后
调用以下代码进 行设置:
ConfigCenter.setShowConnectingStatus(false)
是否清除通知栏通知
Global IM UIKit 支持在打开者会话列表页面和会话页面时,清除通知面板的所有通知。Global IM UIKit 中此开关默认关闭,即不清除通知。
如果需要在会话列表页面时清除通知,请在 App 初始化之后
调用以下代码进行设置:
ConfigCenter.getChatListConfig().setWipeOutNotificationMessage(true)
通过 XML 资源自定义 UI
Global IM UIKit 支持更改会话列表与其中会话条目的展示样式。如果默认展示样式不能满足需求,您可以通过修改 XML 资源文件修改背景、字 体颜色或调整布局里各组件位置等。
Global IM UIKit 资源文件 | 位置 | 说明 |
---|---|---|
rc_chat_list_activity.xml | res/layout | 会话列表页的 Activity 的资源文件。复制 Global IM UIKit 提供的 XML 资源文件,在应用程序项目下创建 /res/layout 下创建同名文件。 |
rc_chat_list_module.xml | res/layout | ChatListFragment 的资源文件。内部是由各个组件 Component 组成。复制 Global IM UIKit 提供的 XML 资源文件,在应用程序项目下创建 /res/layout 下创建同名文件。 |
rc_item_chat_list.xml | res/layout | 会话列表中的每一条会话(item)的展示样式。复制 Global IM UIKit 提供的 XML 资源文件,在应用程序项目下创建 /res/layout 下创建同名文件。 |
修改时不要删除 XML 中的 View,不要修改 ID,否则会导致 SDK 崩溃。
自定义会话条目的展示模板
下表列出了 Global IM UIKit 中内置的会话列表项展示模板。如果需要修改会话列表项的展示逻辑,建议您自定义展示模板,并注册使用。
模板类名 | 适用场景 |
---|---|
PrivateChatListItemProvider.java | 单聊会话的展示模板。 |
BaseChatListItemProvider.java | 会话模板基类,缺省模板,没有匹配到其它模板的会话将以此模板展示。 |
-
创建
CustomChatListProvider
,继承会话模板基类BaseChatListItemProvider
。 -
重写
isItemViewType()
和其它需要自定义的方法。public class CustomChatListProvider extends BaseChatListItemProvider {
@Override
public boolean isItemViewType(BaseChatModel item) {
// 根据业务需要,判断 item 是该模板需要处理的会话时,返回 true, 否则返回 false
// 此处以自定义私聊会话模板为例
return item.mCore.getConversationType().equals(Conversation.ConversationType.PRIVATE);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 根据业务需要,自定义处理
return super.onCreateViewHolder(parent, viewType);
}
@Override
public void bindViewHolder(ViewHolder holder, BaseChatModel model, int position, List<BaseChatModel> list, IViewProviderListener<BaseChatModel> listener) {
// 根据业务需要,自定义处理
super.bindViewHolder(holder, model, position, list, listener);
}
} -
注册自定义模板,或替换 SDK 内置模板。
// 获取会话模板管理器
ProviderManager<BaseChatModel> providerManager = ConfigCenter.getChatListConfig().getProviderManager();
// 用自定义模板替换 SDK 原有私聊会话展示模板
providerManager.replaceProvider(PrivateChatListItemProvider.class, new CustomChatListProvider());
// 注册一个自定义模板
providerManager.addProvider(new CustomSystemConversationProvider());