定制会话消息界面
更新时间: 2024/10/31 17:50:12
网易云信 IM UIKit 会话消息模块(chatKit-ui
)提供了单聊和群聊会话消息页面。本文介绍如何基于消息模块快速实现消息 UI 定制和交互事件的单击逻辑定制。
消息组件类型
在单聊和群聊页面中,共用消息组件。消息模块 chatKit-ui
的消息组件中,按照 UI 样式划分为接收消息组件、发送消息组件、通知消息组件和提示消息组件四种类型。
这四种消息组件的源码实现位于 src/main/ets/view/MessageComponent.ets。
组件名称 | 显示效果 | 组件说明 | 组件实现类 |
---|---|---|---|
接收消息组件 | 展示好友发送的消息 UI | ReceiveMessageComponent |
|
发送消息组件 | 展示当前账号发送的消息 UI | SenderMessageComponent |
|
通知消息组件 | 展示通知消息的 UI | NotificationMessageComponent |
|
提示消息组件 | 展示提示消息的 UI | TipsMessageComponent |
消息类型说明
四种消息组件中,通知消息组件和提示消息组件都只用一种 UI 样式,所以绘制 UI 都在 NotificationMessageComponent
和 TipsMessageComponent
。
发送消息组件和接受消息组件的处理对象,包含了多种类型,包括文本消息、图片消息、语音消息等,所以在发送消息组件 SenderMessageComponent
和接受消息组件 ReceiveMessageComponent
中,会根据消息类型,再添加不同类型消息的 UI 组件。
接受消息组件和发送消息组件中的消息类型如下表所示:
以下源码实现都位于 src/main/ets/view/MessageComponentBuilder.ets 中。
消息类型 | 显示效果 | 源码实现 |
---|---|---|
文本消息 | textBuilder |
|
图片消息 | imageBuilder |
|
语音消息 | MessageAudioItemView |
|
视频消息 | videoBuilder |
|
表情 | textBuilder |
|
文件消息 | fileBuilder |
|
地理位置 | locationBuilder 只支持展示 |
定制消息组件 UI
如果您需要定制 UI 组件,可以参考下文示例代码通过修改源码的方式快速实现您想要的效果:
示例一:修改头像圆角方角
-
适用场景:修改消息收发的圆角头像改为方型头像。
-
实现方式:无论是当前账号发送消息,还是当前账号接收消息,修改位于src/main/ets/view/MessageComponent.ets 里的方法即可。将
CommonAvatar
组件中borderRadius
参数改为 0 或者您想要的圆角值。- 当前账号发送消息:调用
SenderMessageComponent
的build
方法。 - 当前账号接收消息:调用
ReceiveMessageComponent
的build
方法。
- 当前账号发送消息:调用
-
示例代码:以当前账号发送消息为例。
TypeScript
build() { Column() { if (this.message != null) { if (this.message?.getMessageTime() !== '') { Row() { Text(this.message?.getMessageTime()).fontColor($r('app.color.color_chat_desc')) .fontSize($r('app.float.chat_desc_text_font_size')) // 修改消息发送时间的字体大小、颜色和位置 }.justifyContent(FlexAlign.Center).width('100%').height(20) } RelativeContainer() { Row() { CommonAvatar({ item: new AvatarItem(this.chatUserInfo != null ? this.chatUserInfo?.getCurrentUserAvatarUrl() : '', this.chatUserInfo?.getCurrentUserAvatarName() ?? '', AvatarColorUntil.getBackgroundColorById(this.message.message.senderId), ) }).width(36) .height(36) .borderRadius(20) // 修改当前账号发送的消息,头像圆角值将头像改为圆角或者方型 } .justifyContent(FlexAlign.Center) .width(32) .height(32) .borderRadius(16) .margin({ right: 16, top: 6 }) .alignRules(this.AlignRight) .id("mineAvatar") .onClick((event: ClickEvent) => { this.onAvatarClick?.(this.message) }) ..... ..... }.width('100%').height(getMessageHeight(this.getUIContext(), this.message)) } }.width('100%').padding({ top: 6, bottom: 6 }) }
示例二:修改字体样式
-
适用场景:修改文本消息中,文本的字体大小和颜色。
-
实现方式:修改代码位于 src/main/ets/view/MessageComponentBuilder.ets 里
textBuilder
的build
方法中,将Text
组件中fontSize
和fontColor
参数改为您想要的值即可。此次修改将同时适用于发送和接收的消息。 -
示例代码:
TypeScript
build() { Column() { // Text(message?.message.text?.trimStart().trimEnd()) Text() { ForEach(parseMessageText(this.message), (item: NEEmojiParseResult) => { if (item.text) { Span(item.text) .fontSize($r('app.float.chat_message_text_font_size')) .textCase(TextCase.Normal) .fontColor($r('app.color.color_chat_title')) } else if (item.emoji) { ImageSpan($rawfile(`emoji/${item.emoji.file}`)).width('18') .height('18') .objectFit(ImageFit.Fill) .verticalAlign(ImageSpanAlignment.CENTER) } }) } .fontColor($r('app.color.color_chat_title')) // 文本消息字颜色 .lineHeight(20) .fontSize($r('app.float.chat_subtitle_text_font_size')) // 文本消息字体大小 } .padding({ left: 12, top: 12, bottom: 12, right: 12 }) }
定制消息组件事件
会话页面消息相关的单击事件有三种类型:
- 消息体单击事件:
onItemClick
- 消息体长按事件:
onItemLongClick
- 消息头像单击事件:
onAvatarClick
消息组件事件类型
实现逻辑可以参考单聊页面 ChatP2PPage
和群聊页面 ChatTeamPage
中的具体实现。
事件 |
入参 | 说明 |
---|---|---|
|
|
消息的单击事件,查看图片、播放视频、语音、下载文件。 |
|
|
消息的长按事件,弹窗菜单操作消息。 |
onAvatarClick |
msg: NIMMessageInfo | undefined 单击的消息数据 |
头像单击,跳转到个人页面或者好友信息页面。 |
定制消息组件事件示例
在单聊中定制消息组件事件的示例代码如下所示:
TypeScriptMessageComponent({
message: msg,
chatInfo: this.chatUserInfo,
// 头像单击
onAvatarClick: ((msg: NIMMessageInfo | undefined) => {
if (msg != null) {
// 单击自己的头像跳转到个人页面
if (msg?.message.senderId == ChatKitClient.getLoginUserId()) {
this.pathStack.pushPath({
name: 'MineInfoPage'
})
} else {
// 单击好友的头像跳转到名片页
this.pathStack.pushPath({ name: 'PersonInfoPage', param: msg?.message.senderId })
}
}
}),
// 消息长按,弹出菜单
onItemLongClick: ((event: GestureEvent, msg: NIMMessageInfo | undefined) => {
this.operationMsg = msg
let opMenuWidth = MessageOperationView.computeViewWidth(msg)
if (event.target.area.position.x !== undefined) {
let xPoint = Number(event.target.area.globalPosition.x) +
(Number(event.target.area.width) - opMenuWidth) / 2
if (xPoint < this.operationViewMargin) {
xPoint = this.operationViewMargin;
}
if (xPoint + opMenuWidth + this.operationViewMargin > this.screenWidth) {
xPoint = this.screenWidth - opMenuWidth - this.operationViewMargin;
}
this.operationRect.x = xPoint;
}
if (event.target.area.position.y !== undefined) {
this.operationRect.y =
Number(event.target.area.globalPosition.y) - this.navBarHeight + Number(event.target.area.height)
}
this.showOperationView = true
}),
// 消息体单击事件,查看图片、视频或者下载文件等
onItemClick: (event: ClickEvent, msg: NIMMessageInfo | undefined) => {
if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_IMAGE) {
this.showImageDetail(msg)
} else if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_FILE) {
this.chatViewModel.downLoadAndOpenFile(msg, getContext(this))
} else if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_VIDEO) {
this.showVideoDetail(msg)
}
}
})