跳到主要内容

逐条消息已读功能

提示

IMKit 逐条消息已读功能(消息已读 V5)自 SDK 5.30.0 版本起支持。

IMKit 内置页面中已默认实现逐条消息已读功能。当接收端查看到某条消息时,会发送这条消息的已读回执,发送端则会收到这条消息的已读回执回调,同时刷新消息已读标记图标,例如绿色的对勾图标。

逐条消息已读回执发送逻辑:进入单群聊会话页面后,当某条接收的消息在屏幕中展示后,才会触发这条消息的已读回执的发送。

准备工作

使用本功能前,必须先提交工单开通逐条消息已读功能。功能开通后,单群聊已读回执功能将失效。

已读回执显示开关

逐条消息已读功能开通后,IMKit 客户端的回执显示功能默认开启,在单聊和群聊中默认会展示消息回执。

您可以将 resrc_config.xml 中下面的变量设为 false 来关闭已读回执的显示。

Java
 <bool name="rc_read_receipt">false</bool>

上面变量配置为 false 后,单聊和群聊中的逐条已读回执显示都会被关闭。

您也可以在进入会话列表页面之前,通过下面的代码动态配置已读回执显示支持的会话类型。

Java
// 下面的代码将逐条已读回执显示配置为仅在单聊中支持,群聊中将不显示逐条已读回执。
RongConfigCenter.conversationConfig().setSupportReadReceiptConversationType(Conversation.ConversationType.PRIVATE);

单聊已读回执

在单聊会话中,发送方会实时收到消息的已读状态更新。在 IMKit 内置页面中,单聊已读状态显示在两处:

  1. 会话列表页面:会话列表的每条会话会显示会话中的最后一条消息的预览。如果单聊会话最后一条消息是自己发送的消息,那么会展示已读回执状态的图标。

    • 如果最后一条消息未被对方阅读,默认展示灰色的圆圈图标。
    • 如果最后一条消息被对方阅读,默认展示绿色的对勾图标。
  2. 消息列表页面:在发送方的单聊会话页面,消息的左下角会显示对号,表示对方已读,如果展示灰圈,则表示对方未读。

群聊已读回执

在群聊会话中,发送方会实时收到消息的已读状态更新。在 IMKit 内置页面中,群聊已读状态显示在消息列表页面,消息的左下角会显示消息已读状态。

消息阅读情况说明:

  • 无人阅读时,显示灰色圆圈;
  • 部分人阅读时,显示绿色饼状图,代表已读人数与总人数的占比情况;
  • 所有人已读时,显示绿色对钩。

已读回执详情页面

点击消息左下角已读状态按钮,即可进入已读回执详情页面。单聊会话页面不可点击。

以下是已读回执详情页面相关组件的详细说明:

  • MessageReadDetailActivity: 群组消息已读未读页面的容器类,负责加载并显示 MessageReadDetailFragment
  • MessageReadDetailFragment: 群组消息已读未读页面的核心部分,负责展示已读和未读用户列表,并处理用户交互事件。
  • MessageReadDetailViewModel: 数据和业务逻辑的处理类,负责从服务器获取消息的已读和未读用户数据,并将数据传递给 MessageReadDetailFragment
  • XML 布局: rc_page_message_read_detail.xml

自定义已读回执按钮点击事件

可以设置会话界面操作的监听器,重写 onReadReceiptStateClick 方法来自定义点击事件,返回 true 表示由业务侧处理点击逻辑,SDK 后续逻辑不再执行。

Java
IMCenter.setConversationClickListener(
new ConversationClickListener() {
@Override
public boolean onUserPortraitClick(
Context context,
Conversation.ConversationType conversationType,
UserInfo user,
String targetId) {
return false;
}

@Override
public boolean onUserPortraitLongClick(
Context context,
Conversation.ConversationType conversationType,
UserInfo user,
String targetId) {
return false;
}

@Override
public boolean onMessageClick(
Context context, View view, Message message) {
return false;
}

@Override
public boolean onMessageLongClick(
Context context, View view, Message message) {
return false;
}

@Override
public boolean onMessageLinkClick(
Context context, String link, Message message) {
return false;
}

@Override
public boolean onReadReceiptStateClick(
Context context, Message message) {
return false;
}
});

页面定制化

可以参照 用户托管页面设计 的自定义 Fragment 形式

Java
// 自定义 Fragment(比如:CustomMessageReadDetailFragment)
public class CustomMessageReadDetailFragment extends MessageReadDetailFragment {

// 重写返回自定义的 ViewModel(比如:CustomMessageReadDetailViewModel)
@Override
protected MessageReadDetailViewModel onCreateViewModel(Bundle bundle) {
return new ViewModelProvider(this, new ViewModelFactory(bundle))
.get(CustomMessageReadDetailViewModel.class);
}

@Override
protected void onViewReady(@NonNull MessageReadDetailViewModel viewModel) {
super.onViewReady(viewModel);

// 更改标题内容
headComponent.setTitleText("新标题");

// 重写标题栏返回按钮点击事件
headComponent.setLeftClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 自定义返回按钮的逻辑
}
});

// 重写标题栏右侧按钮点击事件(如果有)
headComponent.setRightClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 自定义右侧按钮的逻辑
}
});

// 设置标题栏右侧按钮图标
headComponent.setRightTextDrawable(R.drawable.rc_right_icon);
}
}


public class CustomKitFragmentFactory extends KitFragmentFactory {
@NonNull
@Override
public MessageReadDetailFragment newMessageReadDetailFragment(@NonNull Bundle args) {
CustomMessageReadDetailFragment fragment = new CustomMessageReadDetailFragment();
fragment.setArguments(args);
return fragment;
}
}


// 设置自定义工厂,在 Application 中初始化 IMUIKit,并设置自定义的 Fragment 工厂
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
// 设置自定义的 Fragment 工厂
IMCenter.setKitFragmentFactory(new CustomKitFragmentFactory());
}
}