聊天消息列表 | 消息长按菜单 |
![]() | ![]() |
MessageListController,其他逻辑均封装在 MessageList 中。方法名 | 参数 | 描述 |
MessageList | conversationID: String | 初始化组件,设置会话 ID。如果是单聊,组成方式为 c2c_userID。如果是群聊,组成方式为 group_groupID。 |
| modifier: Modifier | Jetpack Compose 中用来设置组件的样式、布局、行为和外观。 |
| config: MessageListConfigProtocol | 初始化组件,设置消息列表的样式、操作项、消息过滤和自定义渲染规则,默认值为 ChatMessageListConfig()。 |
| customActions: List<MessageCustomAction> | 初始化组件,设置自定义消息菜单选项,追加在默认操作项之后。 |
| locateMessage: MessageInfo? | 初始化组件,设置定位消息。通常用于从消息搜索结果页跳转消息页同时定位到目标消息。 |
| messageListViewModelFactory: MessageListViewModelFactory? | 创建组件内部 MessageListViewModel 的工厂类。通常情况下,您无需手动创建,组件已提供默认实现。 |
| controller: MessageListController? | 消息列表控制器,选填。通过 rememberMessageListController() 创建后传入,可在外部退出多选模式、发送“正在输入”状态等,详见下方 MessageListController。 |
| onTypingStatusChanged: (Boolean) -> Unit | 对方“正在输入”状态变化回调,true 表示对方正在输入。仅在单聊且 config 的 enableTyping 为 true 时生效。 |
| onMultiSelectStateChanged: (Boolean) -> Unit | 多选模式状态变化回调,true 表示进入多选模式,false 表示退出多选模式。 |
| onUserClick: (String) -> Unit | 初始化组件,设置点击用户头像跳转响应事件,回调参数为被点击用户的 userID。 |
rememberMessageListController() 创建 MessageListController,并传给 MessageList 的 controller 参数后,可以在外部控制消息列表:方法/属性 | 描述 |
exitMultiSelectMode() | 退出多选模式。 |
isInMultiSelectMode(): Boolean | 当前是否处于多选模式。 |
sendTypingStatus(isTyping: Boolean) | 向对方发送自己的“正在输入”状态,通常与 MessageInput 的 typingStatusSender 配合使用。仅在单聊且 enableTyping 为 true 时生效;为减少无效消息,只有对方在最近 30 秒内给您发过消息时才会发送,并且有频率限制。 |
typingState: StateFlow<Boolean> | 对方是否正在输入,效果与 onTypingStatusChanged 回调相同。 |
onUserClick。import androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.systemBarsPaddingimport androidx.compose.runtime.Composableimport androidx.compose.ui.Modifierimport io.trtc.tuikit.chat.uikit.components.messagelist.ui.MessageList@Composablefun MessageListScreen(conversationID: String, onOpenUserProfile: (userID: String) -> Unit) {Box(modifier = Modifier.fillMaxSize().systemBarsPadding()) {MessageList(conversationID = conversationID) { userID ->// 点击用户头像响应事件onOpenUserProfile(userID)}}}
MessageListController 让两个组件协同工作:多选模式下隐藏输入框、按返回键退出多选,以及显示“对方正在输入”提示。import androidx.activity.compose.BackHandlerimport androidx.compose.foundation.layout.Columnimport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.layout.systemBarsPaddingimport androidx.compose.material3.Textimport androidx.compose.runtime.Composableimport androidx.compose.runtime.getValueimport androidx.compose.runtime.mutableStateOfimport androidx.compose.runtime.rememberimport androidx.compose.runtime.setValueimport androidx.compose.ui.Modifierimport androidx.compose.ui.unit.dpimport io.trtc.tuikit.chat.uikit.components.messageinput.ui.MessageInputimport io.trtc.tuikit.chat.uikit.components.messagelist.ui.MessageListimport io.trtc.tuikit.chat.uikit.components.messagelist.ui.rememberMessageListController@Composablefun ChatScreen(conversationID: String) {val messageListController = rememberMessageListController()var isPeerTyping by remember { mutableStateOf(false) }var isMultiSelectMode by remember { mutableStateOf(false) }// 多选模式下,按返回键退出多选BackHandler(enabled = isMultiSelectMode) {messageListController.exitMultiSelectMode()}Column(modifier = Modifier.fillMaxSize().systemBarsPadding()) {if (isPeerTyping) {Text(text = "对方正在输入...", modifier = Modifier.padding(16.dp))}MessageList(conversationID = conversationID,modifier = Modifier.weight(1f),controller = messageListController,onTypingStatusChanged = { isTyping -> isPeerTyping = isTyping },onMultiSelectStateChanged = { isMultiSelect -> isMultiSelectMode = isMultiSelect },onUserClick = { userID ->// 点击用户头像响应事件})// 多选模式下隐藏输入框if (!isMultiSelectMode) {MessageInput(conversationID = conversationID,typingStatusSender = { isTyping ->// 把自己的输入状态发送给对方messageListController.sendTypingStatus(isTyping)})}}}
ChatMessageListConfig 设置样式。ChatMessageListConfig 的构造参数均为可选的命名参数,未设置的属性使用默认值:import androidx.compose.ui.unit.dpimport io.trtc.tuikit.chat.uikit.components.config.MessageAlignmentimport io.trtc.tuikit.chat.uikit.components.messagelist.config.ChatMessageListConfigimport io.trtc.tuikit.chat.uikit.components.messagelist.ui.MessageListval messageListConfig = ChatMessageListConfig(alignment = MessageAlignment.TWO_SIDED, // 自己发送的消息在右侧,其他人的消息在左侧isShowRightAvatar = false, // 不显示右侧(自己发送的消息)的头像isShowTimeMessage = false, // 不显示时间分隔cellSpacing = 16.dp, // 消息之间的间距horizontalPadding = 12.dp // 消息列表的左右边距)MessageList(conversationID = conversationID, config = messageListConfig) { userID ->// 点击用户头像响应事件}
ChatMessageListConfig 中与样式相关的属性说明如下,操作项相关的开关请参见“自定义操作项”:属性名 | 类型 | 描述 | 备注 |
alignment | MessageAlignment | 消息对齐方式 | MessageAlignment.LEFT:所有消息左对齐。MessageAlignment.RIGHT:所有消息右对齐。MessageAlignment.TWO_SIDED:自己发送的消息右对齐,其他人的消息左对齐。默认值为 TWO_SIDED。 |
isShowTimeMessage | Boolean | 是否显示时间消息 | 控制是否在消息之间显示时间分隔。默认值为 true。 |
isShowLeftAvatar | Boolean | 是否显示左侧头像 | 控制显示在左侧的消息是否显示头像,TWO_SIDED 对齐时即其他人发送的消息。默认值为 true。 |
isShowLeftNickname | Boolean | 是否显示左侧昵称 | 控制显示在左侧的消息是否显示昵称。默认值为 true。 |
isShowRightAvatar | Boolean | 是否显示右侧头像 | 控制显示在右侧的消息是否显示头像,TWO_SIDED 对齐时即自己发送的消息。默认值为 true。 |
isShowRightNickname | Boolean | 是否显示右侧昵称 | 控制显示在右侧的消息是否显示昵称。默认值为 true。 |
cellSpacing | Dp | 消息间距 | 控制相邻消息之间的间距。默认值为 10.dp。 |
isShowSystemMessage | Boolean | 是否显示系统消息 | 控制是否显示群提示消息和撤回提示。默认值为 true。 |
isShowUnsupportMessage | Boolean | 是否显示不支持的消息 | 控制是否显示组件无法识别、只能以默认样式展示的消息。默认值为 true。 |
horizontalPadding | Dp | 水平内边距 | 控制消息列表的左右内边距。默认值为 16.dp。 |
avatarSpacing | Dp | 头像间距 | 控制头像与消息内容之间的间距。默认值为 8.dp。 |
isShowReadReceipt | Boolean | 是否显示已读回执 | 控制自己发送的、需要已读回执的消息是否显示已读状态。消息需要由开启了 enableReadReceipt 的 MessageInput 发送。默认值为 false。 |
enableTyping | Boolean | 是否启用“正在输入”功能 | 仅单聊生效,需要配合 MessageListController 使用。默认值为 true。 |
background | MessageListBackground? | 消息列表背景 | 默认值为 null,详见下方“列表背景”。 |
defaultBubbleAppearance、leftBubbleAppearance、rightBubbleAppearance、ownBubbleAppearance、incomingBubbleAppearance | MessageBubbleAppearance? | 消息气泡外观 | 默认值均为 null,详见下方“气泡外观”。 |
setBackgroundColor、setBackgroundGradient、setBackgroundImage 设置消息列表的背景,clearBackground 可清除设置:import io.trtc.tuikit.chat.uikit.components.messagelist.config.ChatMessageListConfigimport io.trtc.tuikit.chat.uikit.components.messagelist.config.MessageListBackground// 纯色背景val colorBackgroundConfig = ChatMessageListConfig().setBackgroundColor(0xFFF5F6F8.toInt())// 渐变背景,至少需要 2 个颜色val gradientBackgroundConfig = ChatMessageListConfig().setBackgroundGradient(colors = intArrayOf(0xFFE8F0FE.toInt(), 0xFFFFFFFF.toInt()),direction = MessageListBackground.GradientDirection.TOP_BOTTOM)// 图片背景val imageBackgroundConfig = ChatMessageListConfig().setBackgroundImage("https://example.com/chat_background.png")
setBackgroundImage 的参数会交给 Coil 加载,支持网络图片 URL、本地文件、Uri、drawable 资源 ID 等。setDefaultBubbleAppearance、setLeftBubbleAppearance、setRightBubbleAppearance、setOwnBubbleAppearance、setIncomingBubbleAppearance 设置消息气泡的外观,对应的 clearXxxBubbleAppearance 方法可清除设置。多个外观按“默认 → 左侧/右侧 → 自己/他人”的顺序逐个字段合并,后者中设置了的字段会覆盖前者,圆角按每个角单独合并:import io.trtc.tuikit.chat.uikit.components.messagelist.config.ChatMessageListConfigimport io.trtc.tuikit.chat.uikit.components.messagelist.config.MessageBubbleAppearanceimport io.trtc.tuikit.chat.uikit.components.messagelist.config.MessageBubbleBackgroundimport io.trtc.tuikit.chat.uikit.components.messagelist.config.MessageBubbleCornerRadiusimport io.trtc.tuikit.chat.uikit.components.messagelist.config.MessageBubbleStrokeval bubbleConfig = ChatMessageListConfig()// 所有气泡的基础外观:四个角的圆角均为 12dp.setDefaultBubbleAppearance(MessageBubbleAppearance(cornerRadius = MessageBubbleCornerRadius.all(12)))// 自己发送的消息:渐变背景,右下角为直角,其余圆角沿用基础外观.setOwnBubbleAppearance(MessageBubbleAppearance(background = MessageBubbleBackground.Gradient(colors = listOf(0xFF4F8BFF.toInt(), 0xFF1C66E5.toInt()),direction = MessageBubbleBackground.GradientDirection.LEFT_RIGHT),cornerRadius = MessageBubbleCornerRadius(bottomRight = 0)))// 收到的消息:白色背景,1dp 描边.setIncomingBubbleAppearance(MessageBubbleAppearance(background = MessageBubbleBackground.Color(0xFFFFFFFF.toInt()),stroke = MessageBubbleStroke(width = 1, color = 0xFFE5E6EB.toInt())))
MessageBubbleAppearance 的字段说明如下,尺寸参数的单位均为 dp,颜色参数为 ARGB 格式的 Int 值:字段 | 类型 | 描述 |
background | MessageBubbleBackground? | 气泡背景,支持 Color(纯色)、Gradient(渐变,至少 2 个颜色)、DrawableResource(drawable 资源 ID)、DrawableValue(Drawable 对象)。 |
cornerRadius | MessageBubbleCornerRadius? | 四个角的圆角半径(topLeft、topRight、bottomRight、bottomLeft),可以通过 MessageBubbleCornerRadius.all(radius) 统一设置。 |
stroke | MessageBubbleStroke? | 描边的宽度和颜色。 |
contentInsets | MessageBubbleInsets? | 气泡与消息内容之间的内边距,在消息内容自身边距的基础上额外增加。可以通过 MessageBubbleInsets.all(value)、MessageBubbleInsets.symmetric(horizontal, vertical) 快速创建。 |
minimumSize | MessageBubbleSize? | 气泡的最小宽度和最小高度。 |
renderConfig.useDefaultBubble 为 true 的自定义渲染器。图片、视频、表情消息默认不带气泡,仅在带有表情回应时包裹一层默认气泡。isSupportXxx 开关控制操作项是否显示:import io.trtc.tuikit.chat.uikit.components.messagelist.config.ChatMessageListConfigimport io.trtc.tuikit.chat.uikit.components.messagelist.ui.MessageListMessageList(conversationID = conversationID,config = ChatMessageListConfig(isSupportCopy = false) // 不展示“复制”) { userID ->// 点击用户头像响应事件}
开关 | 对应操作项 ID | 描述 |
isSupportCopy | MessageActionIDs.COPY | 复制,仅文本消息展示。默认值取决于全局配置。 |
isSupportForward | MessageActionIDs.FORWARD | 转发,仅发送成功的消息展示。默认值为 true。 |
isSupportQuote | MessageActionIDs.QUOTE | 引用,仅发送成功的消息展示。默认值取决于全局配置。 |
isSupportMultiSelect | MessageActionIDs.MULTI_SELECT | 多选,点击后进入多选模式。默认值为 true。 |
isSupportDelete | MessageActionIDs.DELETE | 删除,点击后会先弹出确认框。默认值取决于全局配置。 |
isSupportRecall | MessageActionIDs.RECALL | 撤回,仅自己发送成功、且发送时间在 2 分钟以内的消息展示。默认值取决于全局配置。 |
isSupportConvertToText | MessageActionIDs.CONVERT_TO_TEXT | 转文字,仅发送成功、且当前未显示转写结果的语音消息展示。默认值为 true。 |
isSupportTranslate | MessageActionIDs.TRANSLATE | 翻译,仅发送成功、且当前未显示译文的文本消息展示。默认值为 true。 |
isSupportListenFromHere | MessageActionIDs.LISTEN_FROM_HERE | 从当前听,从该消息开始依次朗读或播放到最新一条消息。默认值为 true。 |
isSupportReaction | 无 | 表情回应。开启后,发送成功的消息的长按菜单末尾会展示“贴表情”入口,消息下方会展示表情回应。该入口不属于可编辑的操作项。默认值为 true。 |
customActions,MessageList 内部会在默认操作项之后(“贴表情”入口之前)添加您增加的自定义选项:import io.trtc.tuikit.chat.uikit.components.messagelist.model.MessageCustomActionimport io.trtc.tuikit.chat.uikit.components.messagelist.ui.MessageListMessageList(conversationID = conversationID,customActions = listOf(MessageCustomAction(ID = "custom.message.share",title = "Share",iconResID = android.R.drawable.ic_menu_share,action = { message ->println("Share Message: ${message.msgID}")})))
MessageCustomAction 的字段说明如下。由于 action 不是最后一个参数,请以 action = { } 命名参数的方式传入:字段 | 类型 | 描述 |
ID | String | 操作项的唯一标识,必填。 |
title | String | 操作项标题。 |
iconResID | Int | 操作项图标的 drawable 资源 ID,为 0 时不显示图标。图标会按主题的文字颜色着色。 |
action | (MessageInfo) -> Unit | 点击操作项时的回调,参数为当前长按的消息。 |
dangerous | Boolean | 是否为危险操作,默认为 false。目前不影响长按菜单的显示样式。 |
ChatMessageListConfig 的 customizeActions 编辑长按菜单。每次长按消息时,组件会先根据开关和消息状态生成默认操作项,再执行 customizeActions 中的代码,然后追加 customActions 中的操作项,最后根据 isSupportReaction 追加“贴表情”入口。editorContext.message 获取当前长按的消息,通过 editorContext.conversationID 获取会话 ID,通过 editorContext.androidContext 获取 Android Context,并调用以下方法编辑操作项:方法 | 描述 |
add(item) | 在末尾添加操作项。item 的 ID 为空白或与已有操作项重复时会抛出 IllegalArgumentException。 |
remove(ID) | 移除指定 ID 的操作项,不存在时返回 false。 |
replace(ID) { item -> ... } | 替换指定 ID 的操作项,不存在时返回 false。替换后的操作项必须保持 ID 不变,否则会抛出异常。 |
insertBefore(anchorID, item) / insertAfter(anchorID, item) | 在锚点操作项之前或之后插入操作项。锚点不存在时返回 false,且不会插入。item 的 ID 规则与 add 相同。 |
moveBefore(ID, anchorID) / moveAfter(ID, anchorID) | 将操作项移动到锚点操作项之前或之后,任意一个 ID 不存在时返回 false。 |
clear() | 移除全部操作项。 |
items | 当前操作项列表的只读快照。 |
import io.trtc.tuikit.atomicxcore.api.message.MessageTypeimport io.trtc.tuikit.chat.uikit.components.messagelist.config.ChatMessageListConfigimport io.trtc.tuikit.chat.uikit.components.messagelist.model.MessageActionIDsimport io.trtc.tuikit.chat.uikit.components.messagelist.model.MessageCustomActionval editActionsConfig = ChatMessageListConfig().customizeActions {// 当前长按的消息val message = editorContext.message// 移除“多选”remove(MessageActionIDs.MULTI_SELECT)// 修改“删除”的标题。ID 保持不变,点击后仍会先弹出确认框replace(MessageActionIDs.DELETE) { action ->action.copy(title = "删除消息")}// 文本消息增加“收藏”if (message.messageType == MessageType.TEXT) {val favoriteAction = MessageCustomAction(ID = "custom.message.favorite",title = "收藏",iconResID = android.R.drawable.star_off,action = { target ->// 收藏消息 target})// 放在“转发”之后;当前消息没有“转发”(例如发送失败)时,追加到末尾if (!insertAfter(MessageActionIDs.FORWARD, favoriteAction)) {add(favoriteAction)}}}MessageList(conversationID = conversationID, config = editActionsConfig)
消息列表操作(默认选项) | 消息列表操作(隐藏复制选项) | 消息列表操作(新增分享选项) |
![]() | ![]() | ![]() |
文档反馈