跳到主要内容

聊天页面

聊天页面是IMKit中最核心的界面之一,它展示了与特定用户或群组的消息历史记录,并提供了消息输入区域用于发送各种类型的消息。本文档将介绍如何在Flutter应用中使用IMKit的聊天页面。

页面效果

聊天页面通常包含以下元素:

  • 消息列表区域,展示历史消息
  • 输入区域,包含文本输入框和功能按钮
  • 表情面板
  • 更多功能面板(发送图片、文件等)

基本用法

  1. 在Flutter应用中使用RCKChatPage组件:
Dart
import 'package:flutter/material.dart';
import 'package:rongcloud_im_kit/rongcloud_im_kit.dart';

class ChatScreen extends StatelessWidget {
// 可以传入完整的会话对象
final RCIMIWConversation conversation;

ChatScreen({required this.conversation});


Widget build(BuildContext context) {
return Scaffold(
body: RCKChatPage(
conversation: conversation,
),
);
}
}
  1. 跳转到聊天页面:
Dart
// 从会话列表跳转到聊天页面
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RCKChatPage(
conversation: conversation,
),
),
);

自定义配置

IMKit提供了丰富的配置选项,可以自定义聊天页面的外观和行为:

Dart
RCKChatPage(
conversation: conversation,
// 聊天页面配置
config: RCKChatPageConfig(
// 背景配置
backgroundConfig: RCKBackgroundConfig(
// 背景颜色
color: Colors.grey[100],
// 背景图片(可选)
image: AssetImage('assets/chat_bg.jpg'),
),
// 气泡配置
bubbleConfig: RCKBubbleConfig(
// 自己消息的气泡颜色
senderColor: Colors.blue[100],
// 对方消息的气泡颜色
receiverColor: Colors.white,
// 文本样式配置
textStyleConfig: RCKTextStyleConfig(
// 发送方文本样式
senderTextStyle: TextStyle(color: Colors.white),
// 接收方文本样式
receiverTextStyle: TextStyle(color: Colors.black),
// 行间距
lineSpacing: 1.2,
),
// 图片样式配置
imageStyleConfig: RCKImageStyleConfig(
// 图片适应方式
fit: BoxFit.cover,
// 最大宽度
maxWidth: 200,
// 最大高度
maxHeight: 200,
// 缩放比例
scale: 1.0,
// 圆角半径
borderRadius: 10.0,
),
// 语音消息样式配置
voiceStyleConfig: RCKVoiceStyleConfig(
// 播放图标尺寸
iconSize: 24,
// 播放中图标颜色
playingColor: Colors.blue,
// 未播放图标颜色
notPlayingColor: Colors.grey,
),
// 文件消息样式配置
fileStyleConfig: RCKFileStyleConfig(
// 文件图标尺寸
iconSize: 40,
// 文件名样式
fileNameStyle: TextStyle(fontWeight: FontWeight.bold),
// 文件大小样式
fileSizeStyle: TextStyle(color: Colors.grey),
),
// 引用消息样式配置
referenceStyleConfig: RCKReferenceStyleConfig(
// 引用内容背景色
backgroundColor: Colors.grey[200],
// 引用内容文本样式
textStyle: TextStyle(fontSize: 12),
),
),
// 输入配置
inputConfig: RCKMessageInputConfig(
// 输入框配置
inputFieldConfig: RCKInputFieldConfig(
// 输入框提示文本
hintText: '请输入消息...',
// 输入框样式
style: TextStyle(fontSize: 16),
),
// 左侧按钮配置(语音/键盘切换)
leftButtonConfig: RCKInputButtonConfig(
// 按钮图标
icon: Icon(Icons.mic),
// 激活状态下的按钮图标
activeIcon: Icon(Icons.keyboard),
// 按钮尺寸
size: 24,
),
// 右侧按钮配置列表(表情、更多等)
rightButtonsConfig: [
RCKInputButtonConfig(
icon: Icon(Icons.emoji_emotions),
size: 24,
),
RCKInputButtonConfig(
icon: Icon(Icons.add_circle_outline),
size: 24,
),
],
// 表情面板配置
emojiConfig: RCKEmojiConfig(),
// 语音录制配置
voiceRecordConfig: RCKVoiceRecordConfig(),
// 引用消息预览区域配置
quotePreviewConfig: RCKQuotePreviewConfig(),
),
// AppBar配置
appBarConfig: RCKChatAppBarConfig(
// 标题样式
titleConfig: RCKChatTitleConfig(),
// 背景颜色
backgroundConfig: RCKBackgroundConfig(),
),
),
// 消息点击回调
onMessageTap: (message, context) {
// 处理消息点击事件
},
// 消息长按回调
onMessageLongPress: (message, context) {
// 处理消息长按事件
},
// 自定义消息气泡构建器
customChatItemBubbleBuilders: {
// 自定义文本消息气泡
RCIMIWMessageType.text: ({required message, showTime, config}) {
return RCKTextMessageBubble(
message: message,
showTime: showTime,
config: config,
);
},
},
);

大部分 Config 提供了 copyWith 方法,您可以使用它复制已经存在 Config ,方便使用

消息类型与气泡

创建消息需要用到 rongcloud_im_wrapper_plugin库中 的 engine 来创建

IMKit支持多种消息类型,并为每种类型提供了默认的气泡样式:

文本消息

Dart

import 'package:provider/provider.dart';

// 发送文本消息
final chatProvider = context.read<RCKChatProvider>();

// 通过 ChatProvider 发送文本消息
await chatProvider.sendTextMessage("这是一条文本消息");

// 如果需要更多控制,可以通过以下方式创建并发送消息
final engineProvider = context.read<RCKEngineProvider>();
final engine = engineProvider.engine;

// 创建文本消息
RCIMIWTextMessage? textMessage = await engine?.createTextMessage(
RCIMIWConversationType.private,
'user123',
null, // channelId,普通会话为null
'这是一条文本消息'
);

if (textMessage != null) {
// 发送消息
chatProvider.sendMessage(textMessage);
}

图片消息

Dart
// 发送图片消息
final chatProvider = context.read<RCKChatProvider>();

// 通过 ChatProvider 发送图片消息
await chatProvider.addImageMessage(imagePath); // imagePath 是图片的本地路径

// 如果需要更多控制,可以使用底层接口
final engineProvider = context.read<RCKEngineProvider>();
final engine = engineProvider.engine;

// 创建图片消息
RCIMIWImageMessage? imageMessage = await engine?.createImageMessage(
RCIMIWConversationType.private,
'user123',
null,
imagePath // 图片路径
);

if (imageMessage != null) {
// 发送消息
chatProvider.sendMessage(imageMessage);
}

语音消息

Dart
// 发送语音消息
final chatProvider = context.read<RCKChatProvider>();

// 通过 ChatProvider 发送语音消息
await chatProvider.addVoiceMessage(
voicePath, // 语音文件路径
duration // 语音时长(秒)
);

// 如果需要更多控制,可以使用底层接口
final engineProvider = context.read<RCKEngineProvider>();
final engine = engineProvider.engine;

// 创建语音消息
RCIMIWVoiceMessage? voiceMessage = await engine?.createVoiceMessage(
RCIMIWConversationType.private,
'user123',
null,
voicePath, // 语音文件路径
duration // 语音时长(秒)
);

if (voiceMessage != null) {
// 发送消息
chatProvider.sendMessage(voiceMessage);
}

// 播放语音消息
chatProvider.playVoiceMessage(voiceMessage);

// 停止播放语音
chatProvider.stopVoiceMessage();

视频消息

Dart
// 发送视频消息
final chatProvider = context.read<RCKChatProvider>();

// 通过 ChatProvider 发送视频消息
await chatProvider.addSightMessage(
videoPath, // 视频文件路径
duration // 视频时长(秒)
);

// 如果需要更多控制,可以使用底层接口
final engineProvider = context.read<RCKEngineProvider>();
final engine = engineProvider.engine;

// 创建视频消息
RCIMIWSightMessage? sightMessage = await engine?.createSightMessage(
RCIMIWConversationType.private,
'user123',
null,
videoPath, // 视频文件路径
duration // 视频时长(秒)
);

if (sightMessage != null) {
// 发送消息
chatProvider.sendMessage(sightMessage);
}

文件消息

Dart
// 发送文件消息
final chatProvider = context.read<RCKChatProvider>();

// 通过 ChatProvider 发送文件消息
await chatProvider.addFileMessage(filePath); // filePath 是文件的本地路径

// 如果需要更多控制,可以使用底层接口
final engineProvider = context.read<RCKEngineProvider>();
final engine = engineProvider.engine;

// 创建文件消息
RCIMIWFileMessage? fileMessage = await engine?.createFileMessage(
RCIMIWConversationType.private,
'user123',
null,
filePath // 文件路径
);

if (fileMessage != null) {
// 发送消息
chatProvider.sendMessage(fileMessage);
}

自定义消息气泡

对于特定的消息类型,可以自定义气泡的外观:

Dart
RCKChatPage(
customChatItemBubbleBuilders: {
// 自定义文本消息气泡
RCIMIWMessageType.text: ({required message, showTime, config}) {
RCIMIWTextMessage textMessage = message as RCIMIWTextMessage;
return RCKTextMessageBubble(
message: message,
showTime: showTime,
config: config,
);
},
// 自定义图片消息气泡
RCIMIWMessageType.image: ({required message, showTime, config}) {
RCIMIWImageMessage imageMessage = message as RCIMIWImageMessage;
// CustomImageMessageBubble需要您自己实现
return CustomImageMessageBubble(
message: message,
showTime: showTime,
config: config,
);
},
},
);

输入区域扩展

IMKit的输入区域支持扩展,可以添加自定义的功能按钮:

Dart
RCKChatPage(
conversationType: RCIMIWConversationType.private,
targetId: 'user123',
config: RCKChatPageConfig(
inputConfig: RCKMessageInputConfig(
// 扩展菜单配置
extensionMenuConfig: RCKExtensionMenuConfig(
items: [
RCKExtensionMenuItemConfig(
id: 'location',
title: '位置',
icon: Icons.location_on,
onTap: (context) {
// 处理位置发送逻辑
},
),
RCKExtensionMenuItemConfig(
id: 'contact',
title: '名片',
icon: Icons.contact_page,
onTap: (context) {
// 处理名片发送逻辑
},
),
RCKExtensionMenuItemConfig(
id: 'red_packet',
title: '红包',
icon: Icons.card_giftcard,
onTap: (context) {
// 处理红包发送逻辑
},
),
],
),
),
),
);

自定义消息

除了内置的消息类型外,IMKit还支持自定义消息类型:

  1. 在engine初始化和连接之间注册自定义消息:
Dart
// 在应用初始化时注册
engine?.registerNativeCustomMessage('ST:GrpNtf',RCIMIWNativeCustomMessagePersistentFlag.persisted);
  1. 定义自定义消息类:
Dart
import 'package:flutter/material.dart';
import 'package:rongcloud_im_kit/rongcloud_im_kit.dart';
import 'package:provider/provider.dart';

class NativeCustomMessageBubble extends RCKMessageBubble {
NativeCustomMessageBubble(
{super.key,
required super.message,
super.showTime,
super.alignment,
super.withoutBubble,
super.config});


Widget buildMessageContent(BuildContext context, String? refName) {
String operationString = "";
final Map? messageFields = (message as RCIMIWNativeCustomMessage).fields;
final currentUserId = context.read<RCKEngineProvider>().currentUserId;
if (messageFields != null) {
switch (messageFields['operation']) {
case "Create":
{
final operatorUserId = messageFields['operatorUserId'];
String operatorNickname = messageFields['data']['operatorNickname'];
if (operatorUserId == currentUserId) {
operatorNickname = "你";
}

operationString = "$operatorNickname 创建了群组";
}
break;
}
}

return Container(
margin: EdgeInsets.symmetric(horizontal: 10),
child: Text(
operationString,
maxLines: 1,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: RCKThemeProvider().themeColor.textSecondary,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
);
}
}

  1. 进入页面之前把自定义消息气泡当参数传递
Dart
RCKMessageBubble customChatItemBubbleBuilders(
{required RCIMIWMessage message,
bool? showTime,
RCKBubbleConfig? config}) {
if (message.messageType == RCIMIWMessageType.nativeCustom) {
return NativeCustomMessageBubble(
message: message,
showTime: showTime ?? false,
alignment: Alignment.center,
withoutBubble: true,
config: config);
}
return RCKTextMessageBubble(
message: message, showTime: showTime ?? false);
}

itemOnTap(BuildContext context, RCIMIWConversation conversation, index) {
context.read<RCKConvoProvider>().selectConversation(conversation);
Navigator.pushNamed(context, '/chat', arguments: {
'conversation': conversation,
'customChatItemBubbleBuilders': {
RCIMIWMessageType.nativeCustom: customChatItemBubbleBuilders
},
}).then((value) {
if (context.mounted) {
context.read<RCKConvoProvider>().popConversation();
}
});
}

RCKConvoPage(
onItemTap: itemOnTap,
);