定制会话消息界面

更新时间: 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 都在 NotificationMessageComponentTipsMessageComponent

发送消息组件和接受消息组件的处理对象,包含了多种类型,包括文本消息、图片消息、语音消息等,所以在发送消息组件 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 或者您想要的圆角值。

    • 当前账号发送消息:调用 SenderMessageComponentbuild 方法。
    • 当前账号接收消息:调用 ReceiveMessageComponentbuild 方法。
  • 示例代码:以当前账号发送消息为例。

    TypeScriptbuild() {
        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.etstextBuilderbuild 方法中,将 Text 组件中 fontSizefontColor 参数改为您想要的值即可。此次修改将同时适用于发送和接收的消息。

  • 示例代码:

    TypeScriptbuild() {
        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 中的具体实现。

事件
入参 说明

onItemClick

  • event: ClickEvent 单击事件 Event
  • msg: NIMMessageInfo | undefined 单击的消息数据

消息的单击事件,查看图片、播放视频、语音、下载文件。

onItemLongClick

  • event: GestureEvent 事件手势 Event,
  • msg: NIMMessageInfo | undefined 长按的消息数据

消息的长按事件,弹窗菜单操作消息。

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)
                  }
                }
              })
此文档是否对你有帮助?
有帮助
去反馈
  • 消息组件类型
  • 消息类型说明
  • 定制消息组件 UI
  • 示例一:修改头像圆角方角
  • 示例二:修改字体样式
  • 定制消息组件事件
  • 消息组件事件类型
  • 定制消息组件事件示例