跳到主要内容

会话页面

自定义会话页面按钮UI

1.6.0 版本开始,IMKit 支持配置会话页面的 UI 组件。可通过 setConversationContentComponentConfig 接口设置自定义组件配置。

接口定义

TypeScript
setInputAreaComponentConfig(componentConfig: InputAreaComponentConfig): void;

参数说明

ConversationContentComponentConfig

参数名类型必填说明支持版本
identifierComponentIdentifier组件标识,支持的类型:ConversationUnreadMessageButton(未读消息按钮)、ConversationUnreadMentionedMessageButton(未读@我的消息按钮)、ConversationNewReceivedUnreadMessageButton(新收到的未读消息按钮)1.6.0
componentWrappedBuilder<[ConversationContentComponentData]>自定义组件构建器1.6.0

ConversationContentComponentData

参数名类型说明支持版本
contextContext应用上下文对象1.6.0
convIdConversationIdentifier会话标识对象1.6.0
datanumber透传参数。当 identifierConversationNewReceivedUnreadMessageButton 时,代表在会话中新收到的未读消息的数量;当 identifierConversationUnreadMessageButton 时,代表会话中的未读消息数量;当 identifierConversationUnreadMentionedMessageButton 时,代表当前@自己的未读消息的数量1.6.0
conversationViewModelIConversationViewModel会话页面 ViewModel,用来执行后续的事件。当 identifierConversationNewReceivedUnreadMessageButton 时,调用 onClickNewReceivedUnreadMessageButton 执行新收到未读消息的点击事件;当 identifierConversationUnreadMessageButton 时,调用 onClickUnreadMessageButton 执行未读消息的点击事件;当 identifierConversationUnreadMentionedMessageButton 时,调用 onClickUnreadMentionedMessageButton 执行未读@我的消息的点击事件1.6.0

IConversationViewModel

方法名返回值说明支持版本
onClickUnreadMessageButtonvoid进入会话时展示的未读消息的组件点击事件1.6.0
onClickUnreadMentionedMessageButtonvoid进入会话时展示的未读@我的消息的组件点击事件1.6.0
onClickNewReceivedUnreadMessageButtonvoid在进入会话后收到未读新消息的组件点击事件1.6.0
getInputTextAreaContentstring获取输入框当前的文本输入组件的内容1.7.1
getMessageListUiMessage[]获取消息列表。注意:该返回列表仅用于读取,不建议修改1.7.1
refreshUiMessagevoid刷新某条消息1.7.1

使用示例

以下展示了进入会话后收到未读新消息的组件的自定义示例:

  1. 使用 alignRules 控制在屏幕中的位置
  2. 使用 ConversationContentComponentData.data 观察未读消息数
  3. 使用 ConversationContentComponentData.conversationViewModel 暴露会话页面能力,用来处理点击事件

示例 1:自定义未读消息按钮

TypeScript
@Builder
export function buildCustomConversationTopUnreadMessageButton(data: ConversationContentComponentData) {
CustomConversationTopUnreadMessageButton({ context: data.context, convId: data.convId, unreadMessageCount: data.data, viewModel:data.conversationViewModel })
}

@Component
export struct CustomConversationTopUnreadMessageButton {
@Prop context: Context;
@Prop convId: ConversationIdentifier;
@Prop unreadMessageCount: number;
@Prop viewModel: IConversationViewModel;

build() {
if (this.unreadMessageCount > 10) {
Row() {
Image($r('app.media.rc_arrow')).width(12).height(9).objectFit(ImageFit.Contain)
Text((this.unreadMessageCount > 99 ? "99+" : this.unreadMessageCount) + "条新消息")
.fontSize(14)
.fontColor($r('app.color.rc_color_111F2C'))
.margin({ left: 6 })
}
.borderRadius({ topLeft: 24, bottomLeft: 24 })
.height(48)
.padding({ left: 10, right: 10 })
.backgroundColor($r('app.color.rc_color_FFFFFF'))
.alignRules({
center: { anchor: "__container__", align: VerticalAlign.Center },
right: { anchor: "__container__", align: HorizontalAlign.End }
})
.margin({ top: 14 })
.onClick(() => {
this.viewModel.onClickUnreadMessageButton()
})
}
}
}

// 设置UI组件
let ConversationUnreadMessageButton: ConversationContentComponentConfig = {
identifier: ComponentIdentifier.ConversationUnreadMessageButton,
component: wrapBuilder(buildCustomConversationTopUnreadMessageButton),
}
RongIM.getInstance().conversationService().setConversationContentComponentConfig(ConversationUnreadMessageButton)

示例 2:设置其他按钮组件

TypeScript
// 自定义收到新的未读消息的UI组件
let ConversationNewReceivedUnreadMessageButton: ConversationContentComponentConfig = {
identifier: ComponentIdentifier.ConversationNewReceivedUnreadMessageButton,
component: wrapBuilder(buildCustomConversationBottomUnreadMessageButton),
}
RongIM.getInstance().conversationService().setConversationContentComponentConfig(ConversationNewReceivedUnreadMessageButton)

// 自定义顶部未读@我的消息的UI组件
let ConversationUnreadMentionedMessageButton: ConversationContentComponentConfig = {
identifier: ComponentIdentifier.ConversationUnreadMentionedMessageButton,
component: wrapBuilder(buildCustomConversationTopUnreadMentionedMessageButton),
}
RongIM.getInstance().conversationService().setConversationContentComponentConfig(ConversationUnreadMentionedMessageButton)

修改消息可撤回的最大时间

IMKit 默认允许在消息发送后 180 秒内撤回。您可以通过全局配置调整该上限,需要在会话页面展示前设置。

接口定义

TypeScript
setMaxRecallDuration(duration: number): void

参数说明

参数名类型必填说明
durationnumber可撤回的最大时间,单位为秒

示例代码

TypeScript
let config = RongIM.getInstance().conversationService().getConversationConfig()
config.setMaxRecallDuration(180)
RongIM.getInstance().conversationService().setConversationConfig(config)

修改撤回后可重新编辑的时间

IMKit 默认允许在消息撤回后 30 秒内可点击重新编辑,仅文本消息支持撤回再编辑。您可以通过全局配置调整该上限,需要在会话页面展示前设置。

接口定义

TypeScript
setMaxEditableDuration(duration: number): void

参数说明

参数名类型必填说明
durationnumber可重新编辑的最大时间,单位为秒

示例代码

TypeScript
let config = RongIM.getInstance().conversationService().getConversationConfig()
config.setMaxEditableDuration(30)
RongIM.getInstance().conversationService().setConversationConfig(config)

修改消息重发开关

IMKit 从 1.4.3 版本开始支持消息发送失败时自动消息重发。

提示

为了跟 iOSAndroid 端现有逻辑保持一致,该配置默认值为为 true

1.4.3 以下版本升级的客户,会改变默认行为,如果不想消息重发,需要主动设置为 false

TypeScript
let config = RongIM.getInstance().conversationService().getConversationConfig()
config.setEnableResendMessage(false)
RongIM.getInstance().conversationService().setConversationConfig(config)

群消息回执配置

IMKit 从 1.7.1 版本开始支持群消息回执支持配置每条消息都显示已读未读信息。该配置默认为false。

TypeScript
let config = RongIM.getInstance().conversationService().getConversationConfig()
config.setEnableShowAllGroupReceipt(true)
RongIM.getInstance().conversationService().setConversationConfig(config)

设置主窗口 WindowStage

从 1.8.0 版本开始,IMKit 支持配置 WindowStage,用于处理 Kit 页面的全屏与非全屏适配。您需要在会话页面展示前完成配置。

提示

配置 WindowStage 有助于 IMKit 正确处理页面布局,确保在不同显示模式下都能正常展示。

TypeScript
export default class EntryAbility extends UIAbility {

onWindowStageCreate(windowStage: window.WindowStage): void {
// 方式一:通过配置设置
let config = RongIM.getInstance().conversationService().getConversationConfig()
config.setMainWindowStage(() => {
return windowStage
})
RongIM.getInstance().conversationService().setConversationConfig(config)

// 方式二:通过 AppStorage 设置
AppStorage.set('windowStage', windowStage)

windowStage.loadContent('pages/SplashPage');
}

}

会话页面事件

IMKit 提供了会话页面事件监听器 ConversationEventListener,可监听会话页面中输入 @ 时跳转用户列表选择用户事件、当输入状态变化时的事件。需要在会话页面展示前设置。

设置/移除会话页面事件监听

您可以使用 RongIMaddConversationEventListenerremoveConversationEventListener 方法添加或移除监听器。

警告

建议在合适的时机移除监听器,避免内存泄露。如果在页面中监听,建议在 aboutToAppear 中添加监听,在 aboutToDisappear 中移除监听。

参数说明

ConversationEventListener

方法名参数返回值说明
onInputMentionselect: (user: UserInfoModel) => voidvoid输入 @ 时触发。select 为回调函数,在选择用户后调用,将用户信息传递给 SDK
onEditChangeisEditing: booleanvoid输入状态变化时触发。isEditingtrue 表示正在编辑,false 表示停止编辑

示例代码

TypeScript
// 添加监听器
RongIM.getInstance().conversationService().addConversationEventListener(listener);
// 移除监听器
RongIM.getInstance().conversationService().removeConversationEventListener(listener);

使用示例

示例 1:输入 @ 时跳转页面并返回数据

当会话页面输入框输入 @ 时,会触发 onInputMention 方法。如果未设置,SDK 默认不处理该事件。

处理流程:

  1. 收到 onInputMention 时跳转到用户列表页面选择用户
  2. 返回到当前页面后,调用 select 回传 UserInfoModel 给 SDK
TypeScript
let conversationEventListener: ConversationEventListener = {
onInputMention: (select: (user: UserInfoModel) => void) => {
if (this.conId.conversationType === ConversationType.Group) {
// 1. 跳转到用户列表页面选择用户
// new NavPathStack().pushPath();

// 2. 调用 select 回传 UserInfoModel 给 SDK
const userInfo = new UserInfoModel('userId', 'userName', '')
select(userInfo);
}
}
}

示例 2:监听输入状态变化

当会话页面输入状态发生变化时,会触发 onEditChange 方法。如果未设置,SDK 默认不处理该事件。

TypeScript
let conversationEventListener: ConversationEventListener = {
onEditChange: (isEditing: boolean) => {
// isEditing 代表输入状态发生变化
}
}

会话页面代理接口

IMKit 提供了会话页面代理接口 ConversationComponentDelegate,可监听会话页面生命周期。

参数说明

ConversationComponentDelegate

方法名/属性名类型说明支持版本
onViewModelBind(vm: IConversationViewModel) => voidIConversationViewModel 的创建回调。可在此方法中获取 ViewModel 实例1.7.1
onViewModelClear() => voidIConversationViewModel 的清理回调。在页面销毁时调用1.7.1
componentVisibilityConfigMap<ComponentIdentifier, Visibility>当前会话输入区域组件可见性配置。仅影响当前 ConversationComponent 会话页面1.10.0

IConversationViewModel

方法名参数返回值说明支持版本
onClickUnreadMessageButtonvoid进入会话时展示的未读消息的组件点击事件-
onClickUnreadMentionedMessageButtonvoid进入会话时展示的未读@我的消息的组件点击事件-
onClickNewReceivedUnreadMessageButtonvoid在进入会话后收到未读新消息的组件点击事件-
onChangeInputTextAreaContenttext: stringvoid更新输入框的文本组件的内容1.7.0
getInputTextAreaContentstring获取输入框当前的文本输入组件的内容1.7.0
getMessageListUiMessage[]获取消息列表。注意:该返回列表仅用于读取,不建议修改1.7.1
refreshUiMessagemessage: Messagevoid刷新某条消息1.7.1
onScrollToMessagesentTime: numberPromise<boolean>滑动定位到指定消息, 参数 sentTime 是消息的发送时间, 返回 true 表示消息定位成功,false 表示未查找到该消息25.12.0

使用示例

示例 1:获取 ViewModel

构建 ConversationComponentDelegate 接口传给 ConversationComponent,在 onViewModelBind 方法中可以拿到 IConversationViewModel

TypeScript
@Component
struct CustomChatPage {
private vm: IConversationViewModel | undefined
private delegate: ConversationComponentDelegate = {
onViewModelBind: (vm: IConversationViewModel) => {
this.vm = vm;
},
onViewModelClear: () => {
this.vm = undefined
}
}

build() {
ConversationComponent({
conversationData: this.conversationComponentData,
pageShow: this.pageShow,
isEdit: this.isEdit,
delegate: this.delegate,
}).layoutWeight(1)
}
}

示例 2:按会话维度控制输入框按钮可见性

componentVisibilityConfig 支持按会话设置输入区按钮的可见性,满足"一个用户在多个会话使用不同扩展能力"的诉求。

提示
TypeScript
@Component
struct CustomChatPage {
private vm: IConversationViewModel | undefined
private delegate: ConversationComponentDelegate = {
onViewModelBind: (vm: IConversationViewModel) => {
this.vm = vm;
},
onViewModelClear: () => {
this.vm = undefined
},
componentVisibilityConfig: new Map([
[ComponentIdentifier.InputBarVoiceButton, Visibility.None],
[ComponentIdentifier.InputBarEmoticonButton, Visibility.Visible],
[ComponentIdentifier.InputBarSendButton, Visibility.Visible],
[ComponentIdentifier.InputBarPluginButton, Visibility.None],
])
}

build() {
ConversationComponent({
conversationData: this.conversationComponentData,
pageShow: this.pageShow,
isEdit: this.isEdit,
delegate: this.delegate,
}).layoutWeight(1)
}
}