Flutter

最近更新时间:2024-08-26 11:31:42

我的收藏

什么是 TUIKit

TUIKit 是基于 腾讯云 IM SDK 开发的一款即时通讯 UI 组件库,包括会话、聊天、搜索、关系链、群组、音视频通话等能力。通过 TUIKit,可快速集成包含 UI 界面的全平台即时通讯应用。
TUIKit 简化了基于 腾讯云 IM SDK 的应用开发过程。它不仅能助您快速实现 UI 功能,也支持调用 腾讯云 IM SDK 相应的接口实现即时通讯业务逻辑和数据处理。因此,您在使用 TUIKit 时仅需关注自身业务或个性化扩展。
接入前,您可通过 Demo,快速在线体验 TUIKit 各项能力。


概览

目前包含的一级组件如下:
组件名
组件功能
会话列表组件
核心聊天组件
添加好友组件/添加群组组件
黑名单列表组件/新的联系人申请列表组件
好友列表组件/群组列表组件
用户信息组件/群组信息组件
全局搜索组件/会话内搜索组件

准备步骤

环境要求

环境
版本
Flutter
最低要求 Flutter 3.0.0 版本,Dart 2.17.0 版本。
Android
Android Studio Dolphin | 2021.3.1 及以上版本,Android Gradle plugin 4.1.0 以上版本。
iOS
Xcode 12.0 及以上版本,请确保您的项目已设置有效的开发者签名。

支持平台

TUIKit 拥有自适应 UI 界面,可同时用于 移动端 及 桌面端。并支持以下所有平台,针对不同平台有不同的特色能力。方便您一套代码开发全平台应用
平台
支持状态
iOS
支持
Android
支持
Web
支持,0.1.5版本起
macOS
支持,2.0.0 版本起
Windows
支持,2.0.0 版本起
混合开发 (将 Flutter SDK 添加至现有原生应用)
1.0.0版本起支持

前提条件

1. 您已 注册腾讯云 账号,并完成 实名认证
2. 参照 创建并升级应用 创建应用,并记录好 SDKAppID
3. IM 控制台 选择您的应用,在左侧导航栏依次单击 开发辅助 > UserSig 生成&校验 ,创建两个 UserID 及其对应的 UserSig,复制UserID签名(Key)UserSig这三个,后续登录时会用到。
说明:
该账户仅限开发测试使用。应用上线前,正确的 UserSig 签发方式是由服务器端生成,并提供面向 App 的接口,在需要 UserSig 时由 App 向业务服务器发起请求获取动态 UserSig。更多详情请参见 服务端生成 UserSig


接入步骤

如下会介绍如何使用 Flutter TUIKit 快速构建一个简单的即时通信应用。

步骤1:创建 Flutter 应用并添加权限

请参见 Flutter 文档 快速创建一个 Flutter 应用。

配置权限

由于 TUIKit 运行,需要拍摄/相册/录音/网络等权限,需要您在 Native 的文件中手动声明,才可正常使用相关能力。
Android
打开 android/app/src/main/AndroidManifest.xml ,在 <manifest></manifest>中,添加如下权限。
<uses-permission
android:name="android.permission.INTERNET"/>
<uses-permission
android:name="android.permission.RECORD_AUDIO"/>
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission
android:name="android.permission.VIBRATE"/>
<uses-permission
android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.CAMERA"/>
<uses-permission
android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission
android:name="android.permission.READ_MEDIA_VIDEO"/>
iOS
打开 ios/Podfile ,在文件末尾新增如下权限代码。
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
config.build_settings['ENABLE_BITCODE'] = 'NO'
config.build_settings["ONLY_ACTIVE_ARCH"] = "NO"
end
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_MICROPHONE=1',
'PERMISSION_CAMERA=1',
'PERMISSION_PHOTOS=1',
]
end
end
end
说明:
如您需要用到推送能力,还需要添加推送相关权限,详情可查看 Flutter 厂商消息推送插件集成指南

安装 TUIKit

TUIKit 已经内置了 IM SDK,因此您只需要安装 tencent_cloud_chat_uikit ,而不需要再安装基础 IM SDK。
TUIKit 已经开源,您可以引入在线版本,也可以在 GitHub 上 fork 后本地引入使用。在进行后续步骤之前,您可以通过我们的TUIKit介绍页或在线Demo体验来判断现有TUIKit默认样式和您预期的样式之间的差异。

如果差异不是特别大,建议您引入我们的在线版本,并使用组件开放的配置参数和builder进行微调。
flutter pub add tencent_cloud_chat_uikit
如果差异较大,我们更建议您fork一份我们的 TUIKit 源码,并直接修改fork后的版本,并将其引入您的项目中。如果需要更新至我们的最新版本,您可以使用 git upstream 的方式,将新版本的更改从我们的GitHub仓库同步到您的fork仓库中。
如果您的应用还需要部署至 Web / macOS / Windows 版本,还需要参考此说明,额外几步引入增补包。

步骤2:初始化

注意:
如果您需要同时使用 IM TUIKit 和 音视频通话 Callkit,请务必确保本步骤 IM 的初始化及登录完成后,再执行 Callkit 的初始化相关操作。
为尊重表情设计版权,IM Demo/TUIKit 工程中不包含大表情元素切图,正式上线商用前请您替换为自己设计或拥有版权的其他表情包。下图所示默认的小黄脸表情包版权归腾讯云所有,可有偿授权使用,如需获得授权可 提交工单 联系我们。



1. 在您应用启动时,初始化 IM。
2. 请务必保证先执行 TIMUIKitCore.getInstance() ,再调用初始化函数 init() ,并将您的sdkAppID传入。
3. 为方便您获取API报错及建议提醒用户的提示语,此处建议挂载一个 onTUIKitCallbackListener 监听,详见此部分
/// main.dart
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';

final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance();
@override
void initState() {
_coreInstance.init(
sdkAppID: 0, // Replace 0 with the SDKAppID of your IM application when integrating
// language: LanguageEnum.en, // 界面语言配置,若不配置,则跟随系统语言
loglevel: LogLevelEnum.V2TIM_LOG_DEBUG,
onTUIKitCallbackListener: (TIMCallback callbackValue){}, // [建议配置,详见此部分](https://cloud.tencent.com/document/product/269/70746#callback)
listener: V2TimSDKListener());
super.initState();
}
}
注意:
1. 请在本步骤 await 初始化完成后,才可执行后续步骤。
2. TUIKit 界面语言支持自动或手动在简体中文/繁体中文/英文/日语/韩语间切换。此处语言配置用法,请参考此文档

登录测试账户

1. 此时,您可以使用最开始的时候,在控制台生成的测试账户,完成登录验证。
2. 调用 _coreInstance.login 方法,登录一个测试账户。
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';

final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance();
_coreInstance.login(userID: userID, userSig: userSig);
说明:
在下方的步骤3-5中,我们将教您如何使用我们常用组件的最基础用法,移动端和桌面端保持一致,使用同一套代码和文件
而在 步骤6 中,我们将教您如何将这些组件拼装成一个整体,即分别搭建移动端和桌面端的整体架构。在整体架构层面,部分内容需要单独适配。

步骤3:实现 - 会话列表页面

您可以以会话列表作为您的 IM 功能首页,其涵盖了与所有有聊天记录的用户及群聊的会话。



请创建一个 Conversation 类,body 中使用 TIMUIKitConversation 组件,渲染会话列表。
您仅需传入一个 onTapItem 事件的处理函数,用于跳转至具体会话聊天页的导航。关于 Chat 类,会在下一步讲解。
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';

class Conversation extends StatelessWidget {
const Conversation({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
"Message",
style: TextStyle(color: Colors.black),
),
),
body: TIMUIKitConversation(
onTapItem: (selectedConv) {
// 如果需要适配桌面端,此处需要参考 Demo 代码修改。
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
selectedConversation: selectedConv,
),
));
},
),
);
}
}

步骤4:实现 - 会话聊天页面

该页面由顶部主体聊天历史记录及底部发送消息模块组成。



请创建一个 Chat 类,body 中使用 TIMUIKitChat 组件,渲染聊天页面。
建议您传入一个 onTapAvatar 事件的处理函数,用于跳转至联系人的详细信息页。关于 UserProfile 类,会在下一步讲解。
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';

class Chat extends StatelessWidget {
final V2TimConversation selectedConversation;
const Chat({Key? key, required this.selectedConversation}) : super(key: key);
String? _getConvID() {
return selectedConversation.type == 1
? selectedConversation.userID
: selectedConversation.groupID;
}
@override
Widget build(BuildContext context) {
return TIMUIKitChat(
conversation: selectedConversation,
onTapAvatar: (_) {
// 如果需要适配桌面端,此处需要参考 Demo 代码修改。
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserProfile(userID: userID),
));
}, // Callback for the clicking of the message sender profile photo. This callback can be used with `TIMUIKitProfile`.
);
}
如果您的业务场景,不是直接从 Conversation Widget 进入Chat Widget,那么将无法自动获得 上方代码中的 V2TimConversation selectedConversation 会话对象。此时,您可根据以下方法,手动 new 一个 V2TimConversation 对象实例,传入 TIMUIKitChat 组件中。
TIMUIKitChat(
conversation: V2TimConversation(
conversationID: "c2c_10040818", // 单聊:"c2c_${对方的userID}" ; 群聊:"group_${groupID}"
userID: "", // 仅单聊需要此字段,对方userID
groupID: "", // 仅群聊需要此字段,群groupID
showName: "", // 顶部 AppBar 显示的标题
type: 1, // 单聊传1,群聊传2
// 以上是最简化最基础的必要配置,您还可在此指定更多参数配置,根据 V2TimConversation 的注释
),
// ......其他 TIMUIKitChat 的配置参数
);

步骤5:实现 - 用户详情页面

该页面默认,可在只传入一个 userID 的情况下,自动根据是否是好友,生成用户详情页。
请创建一个 UserProfile 类,body 中使用 TIMUIKitProfile 组件,渲染用户详情及关系链页面。
说明:
如果您希望自定义该页面,请优先考虑使用 profileWidgetBuilder 传入需自定义的 profile 组件并配合 profileWidgetsOrder 确定纵向排列顺序;如果无法满足,才可使用 builder



import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';

class UserProfile extends StatelessWidget {
final String userID;
const UserProfile({required this.userID, Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
"Message",
style: TextStyle(color: Colors.black),
),
),
body: TIMUIKitProfile(
userID: widget.userID,
),
);
}
}
此时,您的应用已经可以完成消息收发,管理好友关系,展示用户详情及展示会话列表。

步骤6:搭建应用整体架构

在 TUIKit 2.0.0 版本之后,我们实现了自适应移动端和桌面端的 UI 布局,同时保持了组件用法的一致性。
然而,在应用架构方面,您仍需要针对移动端和桌面端两种不同的模式进行独立适配,包括组件的放置位置、组件间的跳转方式以及页面的整体布局。

平台识别及组件选用

在深入了解本部分内容之前,我们将首先指导您如何利用 TUIKit 提供的方法进行平台识别及平台组件选择,以确保您的业务代码与我们的 TUIKit 组件内部实现的效果保持一致性。
以下功能是我们为桌面端适配开发的通用功能,TUIKit 内部已经实现了这些功能,您可以在您的项目中直接使用。
屏幕类型适配方案
为了实现移动和桌面端的适应,我们推荐您本方案。它可以根据屏幕是桌面宽屏还是手机竖屏来决定展示方式和务逻辑。此方案还能够完成 Web 端的适配。
您可以通过执行以下代码来判断是否为桌面端。通常情况下,无需传入 context,仅在应用启动后第一次执行时需要。
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';

final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
系统平台识别
尽管在大多数情况下屏幕类型判断足以适配桌面端,但在某些特定场景下仍需当前系统类型例如,分别申请各系统的隐私权限,分别获取各系统的存储路径等。
此外,根据相关隐私政策,建议您不要频繁调用系统API以获取当前系统类型。因此,我们推荐您使用我们提供的系统平台识别能力进行此操作。我们仅在应用启动时获取一次系统类型,并将其存储在全局变量中,以便后续调用时直接返回该参数。
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';

final bool isAndroid = PlatformUtils().isAndroid; // 判断当前是否是 Android 设备
final bool isWeb = PlatformUtils().isWeb; // 判断当前是否是网页
final bool isIOS = PlatformUtils().isIOS; // 判断当前是否是 iOS 设备
final bool isWindows = PlatformUtils().isWindows; // 判断当前是否是 Windows 桌面系统
final bool isMacOS = PlatformUtils().isMacOS; // 判断当前是否是 macOS 桌面系统
final bool isMobile = PlatformUtils().isMobile; // 判断当前是否是手机 app 应用,包含了 Android 及 iOS 设备。
final bool isDesktop = PlatformUtils().isDesktop; // 判断当前是否是桌面端应用,包含了 Windows 及 macOS 系统。
根据平台自动选择对应 Widget
在进行桌面端与移动端适配兼容时,有时仅进行细微调整可能不够。可能需要动态展示两个不同的 Widget。例如,一个组件在移动端需要占据整个页面,具备相应的 ScaffoldAppbar,而在桌面端,仅需作为一个 Modal 弹窗。针对这种场景,我们开发了一个通用的 TUIKitScreenUtils.getDeviceWidget() 方法,传入移动端和桌面端的组件,根据平台类型自动返回对应的组件。
使用该方法的示例如下:
TUIKitScreenUtils.getDeviceWidget(
desktopWidget: Container(), // 桌面端 Widget。
defaultWidget: Container(), // 默认 Widget,必传。当对应平台的 Widget 没有传入时,用此 Widget 兜底。
mobileWidget: Container(), // 移动端 Widget。
);
假设我们想实现一个组件,在移动端需要占据整个页面,具备相应的 ScaffoldAppbar,而在桌面端则不需要。可以将核心组件部分抽离,使用该方法为移动端添加一个 Scaffold 框架,而桌面端则不需要该框。示例代码如下:
@overrideWidget
build(BuildContext context) {
Widget widgetBody() {
return const TIMUIKitBlackList(); // 这里替换成实际需要展示的 Widget
}
return TUIKitScreenUtils.getDeviceWidget(
desktopWidget: widgetBody(), // 桌面端直接展示组件
defaultWidget: Scaffold( // 如非特殊情况,移动端可以使用 defaultWidget 默认,包含 Scaffold
appBar: AppBar(),
body: widgetBody(),
)
);
}

整体架构设计实践

说明:
如果您的应用需要一套代码同时支持移动端和桌面端,我们建议您先阅读移动端部分,再阅读桌面端部分;如果只需要特定平台,可以单独阅读相应平台的实现。
移动端
桌面端
为了获得更好的展示效果,我们的一级组件通常需要独占一整个手机页面。
但是,为了帮助您更好地完成自定义匹配您的业务需求,我们的一级组件都不会内部处理多组件间的跳转,除 TIMUIKitChat 外还不包含 ScaffoldAppbar
这意味着,在使用我们的一级组件时,您需要根据业务需求决定是否以及如何配置 ScaffoldAppbar,并监听暴露出来的点击事件和其他需要跳转的事件,处理 Navigator.push() 跳转。
例如,在上方的步骤3中,我们演示了如何通过监听 TIMUIKitConversation 会话列表组件的 onTapItem 点击某个会话的事件回调,跳转至具体某个会话聊天页面。
TIMUIKitConversation(
onTapItem: (selectedConv) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
selectedConversation: selectedConv,
),
)
);
}
);
当然,您还可以根据需要,为这些 dart 文件实现的一级组件类,可选配置 ScaffoldAppbar。因 TIMUIKitChat 的顶部 Appbar 逻辑较为复杂,例如包含 “对方正在输入中” 及 “未读数” 展示等等功能,因此TIMUIKitChat 包含了 ScaffoldAppbar,其余一级组件不包含。
当然,大部分从我们一级组件自动跳转进入的二级或更深层级的组件,如群管理页面组件,因导航逻辑在组件内部处理,且业务模块较为独立。因此包含了ScaffoldAppbar
说明:
对于此类 Appbar,您可通过配置主题的方式,配置 appbarBgColor appbarTextColor chatHeaderBgColor chatHeaderTitleTextColor 等参数以自定义颜色及样式。

整体布局

说明:
本部分下方即将介绍的所有整体布局及架构实现,仅为提供一个可行的思路及其配套 Demo 代码。您可以根据自己的业务需要,自定义完成这些流程的开发。
桌面端的整体架构和移动端较为不同。
区别于移动端通过 Navigator.push() 导航路由的方式切换不同组件及页面,桌面端不太适合频繁进行整体的导航。
相信大家在使用微信/新版QQ/飞书等桌面端 IM 软件中已经有所体会,所有的交互操作,都在同一个窗口中完成。通过左侧 Tab 的方式,切换右侧的核心模块。
常见的模块包括:
左侧 Tab icon
右侧模块内容
聊天
会话列表 + 每个具体的聊天 + 联系人信息 + 群组信息
通讯录
(联系人列表 or 群组列表) + (联系人 or 群组详情)
我的
设置 or 配置个人信息
头像
配置个人信息
因此,我们建议您采用,建立一个类似于我们 Demo 的 home_page.dart 文件,完成这个两栏式布局。维护一个 index 用于确定当前所在页面,左侧防止一个 LeftBar 用于切换 Tab;右侧放置一个使用 Expand 撑开的 IndexedStack 放置核心页面内容。
此整体架构布局的设计实践,可参考我们的 Demo 源码桌面端适配部分代码


现在,基于上方提供的 Demo 源码,分别简单介绍一下几个右侧常见的页面,用于上图 Expand(IndexedStack) 部分,的架构布局设计实践。
1. 会话列表及会话聊天页面
建议您,参考我们的 Demo 代码,新建一个 dart 文件,用于放置 ConversationAndChat Widget 类,用于承载本部分业务逻辑。
这个类,可以引入您在前序步骤制作的 Chat, Conversation, UserProfile 组件,并基本保持这几个用于承载一级组件的 class 代码不变。
这个类采用 Row 布局,左侧放置 ConstrainedBox 用于限制宽度的 Conversation 组件,右侧可用 Expand 撑开放置 Chat 组件。此外,还可以 Stack 配合 AnimatedPositioned 动画修改位置的形式,在最右侧浮动一个 UserProfileGroupProfile 组件,用于点击查看联系人或群组详情,在点击时从屏幕外侧进入,并在用完后,回到屏幕外侧。
这个 ConversationAndChat 类需要包含状态,记录当前的 V2TimConversation? currentConversation 会话。
为上方步骤 3 制作的 Conversation Widget 类,如此段 Demo 代码所示,新增一个对外暴露的方法:onConversationChanged。用于将当前用户点击的会话回调至此。
监听这个 onConversationChanged 事件,并将当前切换至的会话,通过 setState 的方式,记录,并传入 Chat 组件,用于更改当前右侧显示的会话聊天。



2. 联系人页面
联系人页面,通常需要包含以下几个能力:展示联系人列表 / 展示加入的群聊列表/ 展示新的好友申请 / 展示黑名单 / 展示联系人详情 / 展示群组详情 / 搜索联系人或群 / 跳转至会话(单聊和群聊)
为本部分的代码新建一个 dart 文件,并新建一个 ContactsAndProfile Widget 类,用于承载本部分业务逻辑。
本部分的结构,和上方 会话列表及会话聊天页面 类似,一样采用 Row 布局配合 ConstrainedBoxExpand 使用。左侧 ConstrainedBox 用于放置 ContactGroupList 等列表组件,右侧 Expand 用于放置 UserProfileGroupProfile 等信息组件。
具体的实现方式和上方 会话列表及会话聊天页面 类似,这里不再重复阐述。您可参考本部分的 Demo 代码,配合阅读理解。
此外,这个页面有个特殊的特性在于,您可能需要实现跳转至单聊会话或群聊会话的能力,一键进入会话。这部分代码不属于 TUIKit部分,需要您根据自己的业务需要,单独适配。Demo 效果如图所示,图片后有实现思路介绍。


以单聊为例,为您在前序步骤制作的 UserProfile 组件,增加一个自定义按钮和一个 onClickSendMessage 方法,用于将用户点击这个自定义按钮的点击事件抛出。
同样,ContactsAndProfile 也需要配置一个 onNavigateToChat 方法,将监听到的 onClickSendMessage 事件加以转发。
此时,在 home_page.dart 引入这个 ContactsAndProfile 组件的位置,监听这个事件,维护一份在 state 中,并转发至 ConversationAndChat Widget 中。
ConversationAndChat 组件类中,可通过 didUpdateWidget 动态刷新外部传入的 V2TimConversation 会话,更新当前聊天页面和会话列表所在的会话。
为了达到这个目的,还需要为此前制作的 Chat Widget 新增一个 directToChat 方法,让外部可以指定当前所在的会话聊天。
以及,为 Conversation 组件类新增一个 directToChat 方法,让外部可以指定当前所在的会话,以更新展示当前选中的样式。(默认选中的会话是蓝色背景,未选中白色背景,置顶灰色背景)。
此时,即可完成这个从通讯录跳转至会话聊天的能力开发。
3. 其他页面
其他页面的开发思路也类似。
核心还是,尽可能少的修改为每个一级组件配置的全平台通用类,而通过外部页面承载的方式,来实现桌面端适配。
以达到一套代码,一次开发,一个模块全端仅一处维护的目的。
您可参考我们的 Demo 源码中,桌面端适配的部分,完成您的开发。

桌面端特色能力

由于桌面多种种特性,例如切换组件不导航跳转,我们为桌面端也制作了一些特色能力,公共通用组件,供您直接使用
组件一:Modal 弹窗:您可用我们的,也可自定义 TUIKit 中所有弹窗
TUIKit中,大部分在移动端用新页面组件承载的模块,在适配桌面端时,采用了 Modal 弹窗的形式进行处理。
为了保证体验一致性,整个TUIKit中,所有的弹窗均使用同一个组件。该弹窗组件支持配置 标题 / 发送按钮 / 取消按钮 / 宽高 / 位置 等参数。可用于承载二级组件 / 小配置项修改 / 右键菜单 等模块。
1. 您的项目可也用我们的:
您的项目中,如果需要使用弹窗,可以直接选用我们的。保证整个程序中所有弹窗的一致性。


以下展示 showPopupWindow 展示 Modal 的方法的基础用法。更多自定义配置,如展示位置等,可查看该方法注释。
import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';

TUIKitWidePopup.showPopupWindow(
context: context,
title: Modal名称,
operationKey: TUIKitWideModalOperationKey.custom,
width: MediaQuery.of(context).size.width * 0.4, // 宽度
height: MediaQuery.of(context).size.width * 0.5, //高度
child: (onClose) => 具体要展示的内部组件(
groupID: groupID,
controller: _chatController,
onClosed: onClose,
),
);
2. 自定义整个 TUIKit 中所有或部分 Modal 弹窗:
可监听 TIMUIKitConfigshowDesktopModalFunc 方法,并根据提供的参数(如点击确认事件回调 /当前的操作类型 operationKey / 位置)等信息,构建您自己的弹窗。
每次 TUIKit 内部需要弹窗前,都会触发这个回调,并通过 operationKey 字段给您当前弹窗的场景,如果根据 operationKey 判定当前弹窗类型,您需要自定义弹窗,请返回 true 否则返回 false 使用 TUIKit 默认 Modal 弹窗。
组件二:二次确认弹窗



TUIKit中的二次确认弹窗暂不支持自定义,不过如果您的业务代码有需要的话,也可以使用我们的,保证体验相近。
与上方 Modal 类似,调用 TUIKitWidePopup.showSecondaryConfirmDialog() 方法即可。参数和配置可查看注释说明。
组件三:鼠标右键菜单
有别与移动端的长按或侧滑出现菜单的操作,桌面端通常采用点击或鼠标右键出现菜单列表的方式,进行功能交互。如图:



配合上述组件一:TUIKitWidePopup.showPopupWindow() 使用。
提供 TUIKitColumnMenu 菜单列表组件,其中每个菜单项都是一个 ColumnMenuItem 组件,可以定义菜单项的显示 label 文字,左侧 icon 图标,及点击事件。并提供 closeFunc 方法,用于在点击事件末尾,关闭右键菜单。
需要点击的按钮用 InkWell 包裹,监听 onTapDown 等可以获取到 TapDownDetails 的事件,获得点击鼠标位置,并将位置加以传入。当然,这里您还需要根据实际放置位置,考虑边界因素的影响,避免这个菜单出界,利用 min 方法和 MediaQuery.of(context).size 等参数配合决定 offset 位置。
以下展示最基础用法,更多用法可参考方法注释:
return InkWell(
onTapDown: (details){
TUIKitWidePopup.showPopupWindow(
isDarkBackground: false,
operationKey: TUIKitWideModalOperationKey.custom,
borderRadius: const BorderRadius.all(
Radius.circular(4)
),
context: context,
// 下面的 offset 需要根据实际情况及 details 加以计算。
offset: Offset(details.globalPosition.dx + 10, details.globalPosition.dy - 200),
child: (closeFunc) => TUIKitColumnMenu(
data: [
ColumnMenuItem(label: TIM_t("个人中心"), onClick: (){
// 你定义的点击事件
closeFunc();
}),
ColumnMenuItem(label: TIM_t("个人中心"), onClick: (){
// 你定义的点击事件
closeFunc();
}),
],
)
);
},
child: Container(),
);


附加1:TUIKit 的更多能力

您还可以继续使用以下 TUIKit 组件快速实现完整 IM 功能。
TIMUIKitContact:联系人列表页面。
TIMUIKitGroupProfile:群资料页面,使用方式与 TIMUIKitProfile 基本一致。
TIMUIKitGroup:群列表界面。
TIMUIKitBlackList:黑名单列表界面。
TIMUIKitNewContact:联系人(好友)申请列表。如需在外部显示小红点,可使用 TIMUIKitUnreadCount 小红点组件,其会自动挂载监听。
本地搜索TIMUIKitSearch 全局搜索组件,支持全局搜索联系人/群组/聊天记录,也支持使用 TIMUIKitSearchMsgDetail 在特定会话中搜索聊天记录。两种模式取决于是否传入 conversation
UI 组件全貌可参见 本全览文档详细文档。接入过程中,可以参考我们的 Demo 源码

附加2:[选装] 使用 Controller 控制 TUIKit

说明:
建议在 tencent_cloud_chat_uikit 0.1.5 及以后版本中使用本功能。
通过上述步骤的快速集成,您已经可以搭建一套可用的 IM 模块。如果您有其他额外的控制操作需求,可以使用组件配套的 controller 完成。
使用场景如,在会话列表页面中,您可自定义会话 item 的侧滑菜单,提供置顶会话/删除会话/删除历史消息等功能;抑或是发送消息,满足您的额外消息发送需求,例如通过您自行开发的送礼界面发送一条礼物消息。
目前我们提供三个 controller,如下:
组件
控制器
功能
刷新历史消息列表/更新单条消息/手动发送额外的消息/为消息设置自定义字段 等
获取及刷新会话列表/会话置顶/设置会话的草稿/清空会话内所有消息/删除会话/滚动到特定会话等
删除联系人好友/置顶当前联系人的会话/将用户加入黑名单/修改被加好友方式/更新联系人备注名/设置联系人消息免打扰/添加联系人好友/更新自己的资料等
他们的使用方式一致,以 TIMUIKitChatController 举例用法。完整代码可参考DEMO
1. 在使用到 TIMUIKitChat 的类中,实例化一个 TIMUIKitChatController 对象。
final TIMUIKitChatController _chatController = TIMUIKitChatController();
2. 将此对象传入 TIMUIKitChatcontroller 参数中。
@override
Widget build(BuildContext context) {
return TIMUIKitChat(
controller: _chatController,
// ...其他参数
);
}
3. 在这个类中,即可使用控制器,完成自定义操作。例如发送一条地理位置消息:
_sendLocationMessage(String desc, double longitude, double latitude) async {
final locationMessageInfo = await sdkInstance.v2TIMMessageManager
.createLocationMessage(
desc: desc,
longitude: longitude,
latitude: latitude);
final messageInfo = locationMessageInfo.data!.messageInfo;
_chatController.sendMessage(
receiverID: _getConvID(),
groupID:_getConvID(),
convType: _getConvType(),
messageInfo: messageInfo);
}

附加3:[选装] 使用更多插件丰富 TUIKit 使用体验

除 TUIKit 本体基础功能外,我们还提供了四个选装插件,帮助您丰富 IM 能力。
消息推送插件:支持厂商原生离线推送能力及在线推送能力,并支持推送您的其他业务消息,帮助您提高消息触达率。
音视频通话插件:支持类似微信的一对一/群组音视频通话。
自定义表情插件:0.1.5版本后, TUIKit 无自带表情包,需要使用此插件,快速简便集成表情能力。支持 emoji unicode 编码及自定义图片表情。集成过程可参考我们的 Demo
说明
更多实用的插件正在开发中,如果您有好的想法及建议,欢迎随时 联系我们

常见问题

Android 端报错 compileSdkVersion 不合适怎么办?

1. 请在您项目的 pubspec.yaml 文件中,指定确保如下两个插件的版本。
video_thumbnail: ^0.5.3
permission_handler: ^10.0.0
flutter_local_notifications: 9.7.0
2. 修改 android/app/build.gradle 文件,保证 android => compileSdkVersion 33
android {
compileSdkVersion 33
...
}
3. 执行如下命令,重新安装 Android 端依赖。
flutter pub cache clean
flutter pub get

在 Flutter 2.x 上,Android 构建报错 Codepoint 984472 not found in font, aborting. 怎么办?




在您的编译命令中,加入 --no-tree-shake-icons。如:
flutter build apk --no-tree-shake-icons --dart-define=SDK_APPID={您的SDKAPPID}

iOS 端 Pods 依赖无法安装成功怎么办?

尝试方案一:配置运行后,如果报错,可以单击 Product > Clean Build Folder,清除产物后重新 pod installflutter run





尝试方案二:手动删除 ios/Pods 文件夹,及 ios/Podfile.lock 文件,并执行如下命令,重新安装依赖

1. 搭载新款 Apple Silicon 的Mac设备,例如 M1。


cd ios
sudo arch -x86_64 gem install ffi
arch -x86_64 pod install --repo-update
2. 搭载老款 Intel 芯片的 Mac 设备。
cd ios
sudo gem install ffi
pod install --repo-update

佩戴 Apple Watch 时,真机调试 iOS 报错怎么办?




请将您的 Apple Watch 调整至飞行模式,并将 iPhone 的蓝牙功能通过 设置 => 蓝牙 彻底关闭。
重新启动 Xcode(若打开),并重新 flutter run 即可。

Flutter 环境问题如何确认?

如您需得知 Flutter 的环境是否存在问题,请运行 Flutter doctor 检测 Flutter 环境是否装好。

使用 Flutter 自动生成的项目,引入 TUIKit 后,运行 Android 端报错怎么办?




1. 打开 android\\app\\src\\main\\AndroidManifest.xml,根据如下,补全 xmlns:tools="http://schemas.android.com/tools" / android:label="@string/android_label"tools:replace="android:label"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="替换成您的 Android 端包名"
xmlns:tools="http://schemas.android.com/tools">
<application
android:label="@string/android_label"
tools:replace="android:label"
android:icon="@mipmap/ic_launcher" // 指定一个 icon 路径
android:usesCleartextTraffic="true"
android:requestLegacyExternalStorage="true">

2. 打开 android\\app\\build.gradle,补全 defaultConfigminSdkVersiontargetSdkVersion
defaultConfig {
applicationId "" // 替换成您的Android端包名
minSdkVersion 21
targetSdkVersion 30
}


如果国际化界面语言?

国际化界面语言用法详情,或新增其他语言包,请参见 Flutter

如何获取 API 接口调用报错/Flutter 层报错/弹窗提示信息?

请在初始化 TUIKit 时,挂载 onTUIKitCallbackListener 监听。
该监听用于返回包括:SDK API 错误 / Flutter 报错 / 一些可能需要弹窗提示用户的场景信息。
通过TIMCallbackType确定类型。
示例代码如下。您可以根据您的业务需要,修改以下代码,自定义提醒用户的逻辑,包括但不限于弹窗/横幅等。
final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance();

final isInitSuccess = await _coreInstance.init(
onTUIKitCallbackListener: (TIMCallback callbackValue){
switch(callbackValue.type) {
case TIMCallbackType.INFO:
// Shows the recommend text for info callback directly
Utils.toast(callbackValue.infoRecommendText!);
break;
case TIMCallbackType.API_ERROR:
//Prints the API error to console, and shows the error message.
print("Error from TUIKit: ${callbackValue.errorMsg}, Code: ${callbackValue.errorCode}");
if (callbackValue.errorCode == 10004 && callbackValue.errorMsg!.contains("not support @all")) {
Utils.toast(imt("当前群组不支持@全体成员"));
}else{
Utils.toast(callbackValue.errorMsg ?? callbackValue.errorCode.toString());
}
break;
case TIMCallbackType.FLUTTER_ERROR:
default:
// prints the stack trace to console or shows the catch error
if(callbackValue.catchError != null){
Utils.toast(callbackValue.catchError.toString());
}else{
print(callbackValue.stackTrace);
}
}
},
);
下面,分别介绍这三种类型的回调:

SDK API 错误(TIMCallbackType.API_ERROR

该场景下,提供 SDK API 原生errorMsgerrorCode

Flutter 报错(TIMCallbackType.FLUTTER_ERROR

该错误由监听 Flutter 原生抛出异常产生,提供错误发生时的stackTrace(来自FlutterError.onError)或catchError(来自 try-catch)。

场景信息(TIMCallbackType.INFO

建议根据实际情况,将这些信息弹窗提示用户。
具体提示规则和弹窗样式可由您决定。
提供infoCode场景码帮助您确定当前的场景,及默认的提示推荐语infoRecommendText
您可直接弹窗提示我们的推荐语,也可根据场景码自定义推荐语。推荐语语言使用系统语言语言或您指定的语言,请勿根据推荐语来判断场景。
场景码规则如下:
场景码由七位数组成,前五位数确定场景发生的组件,后两位确定具体的场景表现。
场景码开头
对应的组件
66601
TIMUIKitAddFriend
66602
TIMUIKitAddGroup
66603
TIMUIKitBlackList
66604
TIMUIKitChat
66605
TIMUIKitContact
66606
TIMUIKitConversation
66607
TIMUIKitGroup
66608
TIMUIKitGroupProfile
66609
TIMUIKitNewContact
66610
TIMUIKitGroupProfile
66611
TIMUIKitNewContact
66612
TIMUIKitProfile
66613
TIMUIKitSearch
66614
通用组件
全部场景码清单如下:
场景码 infoCode
推荐提示语 infoRecommendText
场景描述
6660101
好友申请已发送
用户申请添加其他用户为联系人
6660102
该用户已是好友
用户申请添加其他已是好友的用户为好友时,触发 onTapAlreadyFriendsItem 回调
6660201
群申请已发送
用户申请加入需要管理员审批的群聊
6660202
您已是群成员
用户申请加群时,判断用户已经是当前群成员,触发 onTapExistGroup 回调
6660401
无法定位到原消息
当用户需要跳转至@消息或者是引用消息时,在消息列表中查不到目标消息
6660402
视频保存成功
用户在消息列表,点开视频消息后,选择保存视频
6660403
视频保存失败
用户在消息列表,点开视频消息后,选择保存视频
6660404
说话时间太短
用户发送了过短的语音消息
6660405
发送失败,视频不能大于 100MB
用户试图发送大于 100MB 的视频
6660406
图片保存成功
用户在消息列表,点开图片大图后,选择保存图片
6660407
图片保存失败
用户在消息列表,点开图片大图后,选择保存图片
6660408
已复制
用户在弹窗内选择复制文字消息
6660409
暂未实现
用户在弹窗内选择非标功能
6660410
其他文件正在接收中
用户点击下载文件消息时,前序下载任务还未完成
6660411
正在接收中
用户点击下载文件消息
6660412
视频消息仅限 mp4 格式
用户发送了一条非 mp4 格式的视频消息
6660413
已加入待下载队列,其他文件下载中
已加入待下载队列,其他文件下载中
6660414
正在下载中
桌面端图片/视频资源正在下载中,暂时无法打开,过一会下载好了才能打开
6660415
视频文件异常
发送的视频文件资源本身是错误或被损坏,无法发送
6661001
无网络连接,无法修改
当用户试图在无网络环境下,修改群资料
6661002
无网络连接,无法查看群成员
当用户试图在无网络环境下,修改群资料
6661003
成功取消管理员身份
用户将群内其他用户移除管理员
6661201
无网络连接,无法修改
当用户试图在无网络环境下,修改自己或联系人的资料
6661202
好友添加成功
在资料页添加其他用户为好友,并自动添加成功,无需验证
6661203
好友申请已发出
在资料页添加其他用户为好友,对方设置需要验证
6661204
当前用户在黑名单
在资料页添加其他用户为好友,对方在自己的黑名单内
6661205
好友添加失败
在资料页添加其他用户为好友,添加失败,可能是由于对方禁止加好友
6661206
好友删除成功
在资料页删除其他用户为好友,成功
6661207
好友删除失败
在资料页删除其他用户为好友,失败
6661401
输入不能为空
当用户在录入信息时,输入了空字符串
6661402
请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法
用户退出群或解散群时,为提供返回首页办法
6661403
设备存储空间不足,建议清理,以获得更好使用体验
在 login 成功后,会自动检测设备存储空间,如果不足1GB,会提示存储空间不足

联系我们

点此进入IM社群,享有专业工程师的支持,解决您的难题。