跳到主要内容

会话列表自定义

会话列表控制需要展示的会话类型

SDK 会话列表默认仅支持单聊和群聊两种会话。

您可以通过 setSupportedTypes 方法配置会话列表展示的会话类型。需要在会话列表展示前设置,最多可以支持单聊、群聊、系统会话。

接口定义

TypeScript
/**
* 设置支持的会话类型
* @param types 会话类型数组
*/
setSupportedTypes(types: ConversationType[]): void

参数说明

参数名类型必填说明
typesConversationType[]会话类型数组,可选值:ConversationType.Private(单聊)、ConversationType.Group(群聊)、ConversationType.System(系统会话)

示例代码

TypeScript
// 读取会话列表当前的配置
let config = RongIM.getInstance().conversationListService().getConversationListConfig()
// 设置会话列表仅展示单聊
config.setSupportedTypes([ConversationType.Private])
// 更新会话列表配置
RongIM.getInstance().conversationListService().setConversationListConfig(config)

会话列表组件自定义聚合展示

您可以通过为 ConversationListComponent 组件设置 dataProcessor 参数,实现更灵活的会话列表数据源管理。

提示
  • 1.7.2 版本开始支持。
  • 一旦使用该参数,将会覆盖前述通过 setSupportedTypes 配置的会话类型展示方式。

接口定义

TypeScript
/**
* 会话列表数据处理器接口
*/
export interface DataProcessor {
/**
* 支持的会话类型
*/
supportedTypes?: ConversationType[];

/**
* 自定义获取会话列表的方法
*/
onFetchConversationList?: (time: number) => Promise<List<Conversation>>;

/**
* 会话数据过滤方法
*/
onConversationFilter?: (item: Conversation) => boolean;
}

参数说明

DataProcessor

参数名类型必填说明
supportedTypesConversationType[]支持的会话类型数组,用于筛选展示的会话类型
onFetchConversationList(time: number) => Promise<List<Conversation>>自定义获取会话列表的方法,参数 time 为时间戳,用于分页加载
onConversationFilter(item: Conversation) => boolean会话过滤方法,返回 true 表示显示该会话,返回 false 表示过滤该会话

使用示例

示例 1:按会话类型筛选

TypeScript
// 仅展示单聊会话
ConversationListComponent({dataProcessor: {
supportedTypes: [ConversationType.Private]
}})

// 仅展示群聊会话
ConversationListComponent({dataProcessor: {
supportedTypes: [ConversationType.Group]
}})

示例 2:自定义聚合逻辑

以获取未读数不为 0 的会话列表为例:

TypeScript
ConversationListComponent({dataProcessor: {
onFetchConversationList: async (time: number) => {
// 自定义请求会话列表数据
const cons = new List<ConversationType>()
cons.add(ConversationType.Group)
cons.add(ConversationType.Private)

const list: List<Conversation> = new List<Conversation>()

const res = await IMEngine.getInstance().getUnreadConversations(cons)
if (res.code === EngineError.Success && res.data && res.data.length > 0) {
res.data.forEach(item => {
list.add(item)
})
options.time = res.data.getLast().lastOperateTime
}

return list
},
// 设置会话数据过滤方法
onConversationFilter: (item: Conversation) => {
return item.unreadMessageCount > 0
}
}})

会话列表增加长按事件

您可以通过 addConversationItemLongClickAction 方法为会话列表添加自定义长按事件。

接口定义

TypeScript
/**
* 长按事件配置接口
*/
export interface ItemLongClickAction<Conversation> {
/**
* 获取长按菜单显示的标题
*/
obtainTitle: (context: Context, data: Conversation) => string | Resource;

/**
* 长按菜单项的点击事件
*/
onClick: (context: Context, data: Conversation) => void;

/**
* 过滤条件,用于控制该长按菜单项是否显示
*/
onFilter: (data: Conversation) => boolean;

/**
* 动作 ID,用于唯一标识该长按事件
*/
actionId: string;
}

参数说明

ItemLongClickAction

参数名类型必填说明
obtainTitle(context: Context, data: Conversation) => string | Resource长按菜单显示的标题,返回字符串或资源 ID
onClick(context: Context, data: Conversation) => void用户点击长按菜单项时触发的回调函数
onFilter(data: Conversation) => boolean过滤条件函数,返回 true 表示显示该菜单项,返回 false 表示不显示
actionIdstring动作的唯一标识符,用于区分不同的长按事件

示例代码

TypeScript
private addConversationListLongClickAction() {
let action: ItemLongClickAction<Conversation> = {
// 显示标题
obtainTitle: (context: Context, data: Conversation): string | Resource => {
return "自定义长按事件";
},
// 长按 item 的点击事件
onClick: (context: Context, data: Conversation) => {
promptAction.showToast({ message: "会话列表自定义长按事件" })
},
// 过滤条件,true 代表需要显示,false 代表不会显示
onFilter: (data: Conversation): boolean => {
// 可以动态配置特定的 Conversation 才显示该长按 item
return true;
},
actionId: 'Conversation_Custom' // 动作 Id,可自定义
}

RongIM.getInstance().conversationListService().addConversationItemLongClickAction(action);
}

会话列表头像圆角控制

您可以通过 setConversationAvatarStyle 方法修改会话列表头像样式。会话列表头像默认为矩形,可以修改为圆形。不支持动态切换矩形和圆形,必须在会话列表展示前设置。

接口定义

TypeScript
/**
* 设置会话列表头像样式
* @param style 头像样式
*/
setConversationAvatarStyle(style: AvatarStyle): void

参数说明

参数名类型必填说明
styleAvatarStyle头像样式,可选值:AvatarStyle.Cycle(圆形)、AvatarStyle.Rectangle(矩形,默认值)

示例代码

TypeScript
// 读取会话列表当前的配置
let config = RongIM.getInstance().conversationListService().getConversationListConfig()
// 设置会话列表头像为圆形
config.setConversationAvatarStyle(AvatarStyle.Cycle)
// 更新会话列表配置
RongIM.getInstance().conversationListService().setConversationListConfig(config)

会话列表点击事件

当您使用 ConversationListComponent 创建会话列表页面时,可以传入 onConversationItemClick 来处理点击事件。SDK 默认未处理点击事件,如未设置 onConversationItemClick 则表现为点击无反应。

提示

1.4.3 版本开始,支持通过 addConversationListEventListener 设置会话列表点击事件,见会话列表事件。但需要注意,如果传入的 onConversationItemClick 不为空则不会再执行 ConversationListEventListeneronConversationClick 回调。

接口定义

TypeScript
/**
* 会话列表 Item 点击事件回调
* @param conversation 被点击的会话对象
* @param index 会话在列表中的索引
*/
onConversationItemClick?: (conversation: Conversation, index: number) => void

参数说明

参数名类型说明
conversationConversation被点击的会话对象,包含会话类型和目标 ID 等信息
indexnumber会话在列表中的索引位置

示例代码

TypeScript
@Entry
@Component
export struct ChatListPage {

build() {
Column() {
ConversationListComponent({
// 实现会话列表的点击事件
onConversationItemClick: this.onConversationItemClick
}).layoutWeight(1)
}.width('100%').height('100%')
}

private onConversationItemClick(conversation: Conversation, index: number): void {
// let params = new Conversation()
// params.conversationType = ConversationType.Private
// params.targetId = "会话 Id"

// 参数必须是 Conversation 对象,必须有有效的 conversationType 和 targetId
router.pushUrl({ url: "pages/ChatPage", params: conversation },);
}
}

会话列表添加自定义空布局

IMKit 支持在会话列表为空时展示自定义的空白视图。您只需在构造 ConversationListComponent 时传入 emptyComponent 即可。

接口定义

TypeScript
/**
* 空布局组件构建器
* 当会话列表为空时显示的自定义组件
*/
emptyComponent?: () => void

参数说明

参数名类型必填说明
emptyComponent() => void空布局组件构建器,用于构建会话列表为空时显示的自定义视图

示例代码

TypeScript
@Entry
@Component
export struct ChatListPage {

build() {
Column() {
ConversationListComponent({
// 实现没有会话的空白页面
emptyComponent: () => {
this.emptyBuilder();
}
}).layoutWeight(1)
}.width('100%').height('100%')
}

@Builder
emptyBuilder() {
Text(`空白页面`).width('95%').fontColor("#FF0000").padding(10)
}
}

会话列表页面事件

IMKit 提供了会话列表事件监听器 ConversationListEventListener,可监听保存草稿、会话清除未读数、删除会话、本端或者其他端修改会话的免打扰和置顶状态、点击会话、长按会话等事件。

您需要使用 addConversationListEventListenerremoveConversationListEventListener 方法添加或移除监听器。建议添加监听后,在合适的时机移除,避免内存泄漏。如果在页面中监听,建议在 aboutToAppear 调用,在 aboutToDisappear 移除监听。

提示

1.4.3 版本开始,增加 onConversationLongClickonConversationClick 方法。

接口定义

TypeScript
export interface ConversationListEventListener {
/**
* 当某个会话内产生保存草稿的行为时
*/
onSaveDraft?: (identifier: ConversationIdentifier, content: string) => void;

/**
* 当某个会话清除未读数时
*/
onClearedUnreadStatus?: (identifier: ConversationIdentifier) => void;

/**
* 当批量删除某些会话时
*/
onRemoveConversation?: (identifierList: List<ConversationIdentifier>) => void;

/**
* 当其他端修改会话的免打扰和置顶状态时
*/
onSyncConversationStatus?: (items: List<ConversationStatusInfo>) => void;

/**
* 当本端修改会话的置顶状态时
*/
onConversationTopStatusChange?: (identifierList: List<ConversationIdentifier>, option: ISetConversationTopOption) => void;

/**
* 当本端修改会话的免打扰状态时
*/
onConversationNotificationLevelChange?: (identifierList: List<ConversationIdentifier>, level: PushNotificationLevel) => void;

/**
* 长按会话列表中的 item 时执行
* @param uiConversation 长按时的会话条目
* @returns 是否处理该事件。返回 true 代表 App 处理该点击事件,SDK 不再处理;返回 false 代表由 SDK 处理点击事件
* @version 1.4.3
*/
onConversationLongClick?: (uiConversation: BaseUiConversation) => boolean;

/**
* 点击会话列表中的 item 时执行
* @param uiConversation 会话条目
* @returns 是否处理该事件。返回 true 代表 App 处理该点击事件,SDK 不再处理;返回 false 代表由 SDK 处理点击事件
* @version 1.4.3
*/
onConversationClick?: (uiConversation: BaseUiConversation) => boolean;
}

方法说明

ConversationListEventListener

方法名参数返回值说明支持版本
onSaveDraftidentifier: ConversationIdentifier
content: string
void当某个会话内产生保存草稿的行为时触发-
onClearedUnreadStatusidentifier: ConversationIdentifiervoid当某个会话清除未读数时触发-
onRemoveConversationidentifierList: List<ConversationIdentifier>void当批量删除某些会话时触发-
onSyncConversationStatusitems: List<ConversationStatusInfo>void当其他端修改会话的免打扰和置顶状态时触发-
onConversationTopStatusChangeidentifierList: List<ConversationIdentifier>
option: ISetConversationTopOption
void当本端修改会话的置顶状态时触发-
onConversationNotificationLevelChangeidentifierList: List<ConversationIdentifier>
level: PushNotificationLevel
void当本端修改会话的免打扰状态时触发-
onConversationLongClickuiConversation: BaseUiConversationboolean长按会话列表 Item 时触发。返回 true 表示 App 处理该事件,SDK 不再处理;返回 false 表示由 SDK 处理。如果存在多个监听器,只要有 1 个监听器实现了该方法且返回 true,SDK 则不再处理该事件1.4.3
onConversationClickuiConversation: BaseUiConversationboolean点击会话列表 Item 时触发。优先执行 ConversationListComponent 传入的 onConversationItemClick,如果没传则执行此方法。返回 true 表示 App 处理该事件,SDK 不再处理;返回 false 表示由 SDK 处理。如果存在多个监听器,只要有 1 个监听器实现了该方法且返回 true,SDK 则不再处理该事件1.4.3

示例代码

TypeScript
let service = RongIM.getInstance().conversationListService();
// 设置监听
service.addConversationListEventListener(conversationListEventListener)
// 移除监听
service.removeConversationListEventListener(conversationListEventListener)

自定义会话列表 Item 子组件

您可以通过调用 setConversationItemComponentConfig 方法,为会话列表的每个 Item 组件添加自定义子组件。

提示

1.7.2 版本开始支持。

接口定义

TypeScript
/**
* 会话列表 Item 扩展组件配置
* @since 1.8.0
*/
export interface ConversationItemComponentConfig {
/**
* 组件标识
*/
identifier: ComponentIdentifier,

/**
* 组件 WrappedBuilder
* @since 1.6.0
*/
component?: WrappedBuilder<ConversationItemComponentData> | null,
}

/**
* 会话列表 Item 扩展组件数据,封装必要的参数透传给自定义组件
* @since 1.8.0
*/
export class ConversationItemComponentData {
/**
* 上下文
*/
context: Context | undefined;
/**
* 会话信息
*/
conversation: BaseUiConversation | undefined;
/**
* 头像配置
* @since 1.10.0
*/
avatarConfig?: AvatarConfig
}

参数说明

ConversationItemComponentConfig

参数名类型必填说明支持版本
identifierComponentIdentifier组件标识,指定要自定义的组件类型。详见下方"支持的组件类型"1.8.0
componentWrappedBuilder<ConversationItemComponentData>自定义组件构建器,用于构建自定义 UI 组件1.6.0

ConversationItemComponentData

参数名类型说明支持版本
contextContext应用上下文对象1.8.0
conversationBaseUiConversation会话信息对象,包含会话的详细数据1.8.0
avatarConfigAvatarConfig头像配置信息,包含头像尺寸等属性1.10.0

支持的组件类型

identifier 支持的组件类型说明:

组件类型说明支持版本
ConversationItemExtensionComponent会话列表 Item 的扩展组件1.7.2
ConversationItemAvatar会话列表 Item 的头像组件1.10.0

使用示例

示例 1:为置顶会话添加自定义图标

为置顶的会话 Item 在右上角增加一个自定义图标:

TypeScript

@Builder
export function buildCustomConversationItemExtensionComponent(componentData: ConversationItemComponentData) {
CustomConversationItemExtensionComponent({
context: componentData.context,
conversation: componentData.conversation,
})
}

@Component
export struct CustomConversationItemExtensionComponent {
@Prop context: Context;
@Prop conversation: BaseUiConversation;

build() {
// 在会话右上角增加自定义置顶图标
if (this.conversation.getConversation().isTop) {
// 您需要将 “app.media.con_top” 替换为您应用中的图片资源
Image($r('app.media.con_top')).width(12).height(12).objectFit(ImageFit.Contain)
.alignRules({
top: {anchor: '__container__', align: VerticalAlign.Top},
right: {anchor: '__container__', align: HorizontalAlign.End}
})
}
}
}

let ConversationItemComponent: ConversationItemComponentConfig = {
identifier: ComponentIdentifier.ConversationItemExtensionComponent,
component:wrapBuilder(buildCustomConversationItemExtensionComponent),
}
RongIM.getInstance().conversationListService().setConversationItemComponentConfig(ConversationItemComponent)

示例 2:自定义会话头像组件

在默认头像基础上添加自定义装饰层:

TypeScript
@Builder
function buildCustomConversationAvatar(data: ConversationItemComponentData) {
// 默认头像 + 自定义装饰层
Stack({ alignContent: Alignment.Center }) {
RongIM.getInstance().uiComponents().getDefaultConversationAvatar().builder(data)
Image($r('app.media.avatar_frame_sample'))
.width(data.avatarConfig?.size)
.height(data.avatarConfig?.size)
.objectFit(ImageFit.Contain)
.hitTestBehavior(HitTestMode.Transparent)
}
}
let ConversationItemComponent: ConversationItemComponentConfig = {
identifier: ComponentIdentifier.ConversationItemAvatar,
component: wrapBuilder(buildCustomConversationAvatar),
}
RongIM.getInstance().conversationListService().setConversationItemComponentConfig(ConversationItemComponent)

自定义会话列表的 dataSource

通过继承 ConversationListDataSource 可以自定义会话列表的数据源,实现对数据源的增、删、改操作。

提示

1.10.0 版本开始支持。

接口定义

TypeScript
/**
* 会话列表数据源基类
*/
export class ConversationListDataSource {
/**
* 替换数据源中的数据
* @param values 新的会话列表数据
*/
public replaceData(values: ArrayList<BaseUiConversation>): void
}

方法说明

ConversationListDataSource

方法名参数返回值说明
replaceDatavalues: ArrayList<BaseUiConversation>void替换数据源中的数据。您可以在此方法中对会话列表数据进行增、删、改操作

使用示例

通过继承 ConversationListDataSource 并重写 replaceData 方法,实现对会话列表的自定义操作:

TypeScript
@Observed
export class CustomDataSource extends ConversationListDataSource {
// 替换 dataSource 数据
public replaceData(values: ArrayList<BaseUiConversation>): void {
// 1) 新增:单聊 targetId = 'customPrivate'
let hasCustomPrivate: boolean = false
for (let item of values) {
const c: Conversation | undefined = item?.getConversation?.()
if (c && c.conversationType === ConversationType.Private && c.targetId === 'customPrivate') {
hasCustomPrivate = true
break
}
}
if (!hasCustomPrivate) {
const newCon = new Conversation()
newCon.conversationType = ConversationType.Private
newCon.targetId = 'customPrivate'
// 示例中的 customUiConversation 为自定义会话对象,需要您自行实现
values.add(new customUiConversation(getContext(), newCon))
}

// 2) 删除:移除单聊会话 targetId = 'user1'
for (let item of values) {
const c: Conversation | undefined = item?.getConversation?.()
if (c && c.conversationType === ConversationType.Private && c.targetId === 'user1') {
values.remove(item)
break
}
}

// 3) 修改:将单聊 targetId = 'user2' 的会话替换为 customUiConversation
let index: number = 0
for (let item of values) {
const c: Conversation | undefined = item?.getConversation?.()
if (c && c.conversationType === ConversationType.Private && c.targetId === 'user2') {
// 示例中的 customUiConversation 为自定义会话对象,需要您自行实现
if (item instanceof customUiConversation) {
item.onConversationUpdate(c, true)
} else {
// 示例中的 customUiConversation 为自定义会话对象,需要您自行实现
const custom = new customUiConversation(getContext(), c)
values.remove(item)
values.insert(custom, index)
}
break
}
index++
}

super.replaceData(values)
}
}