有奖捉虫:行业应用 & 管理与支持文档专题 HOT
说明:
腾讯云 IM Fluter UIKit 接入表情能力,已在2.2.0版本得到大幅优化。用法简单清晰许多,只要简单传入配置项,即可快速启用。不再需要使用本文的
所述的用法,写大量兼容代码。
欢迎将腾讯云 IM Flutter UIKit 升级至2.2.0以上版本,并参见 新版本指引,快速接入。
以下为您介绍,如何为腾讯云 IM Flutter TUIKit 引入表情能力。
我们的 TIMUIKitChat 组件中,支持发送及接收三种类型的表情:
表情类型
发送形式
是否文字混排
发送内容
解析方式
引入方式
TUIKit默认自带
Unicode Emoji 表情
文本消息
Unicode编码
设备自动将 Unicode 编码解析成小表情。不同的设备,对Unicode解析后的图形,略有不同
Unicode List
文档中提供一套默认 Unicode 列表示例
小图片表情
文本消息
表情图片名称
根据名称,自动匹配本地 Asset 图片资源
图片资源预存于Asset,并定义 List
一套 QQ 同款小表情图库,可直接使用
大图片表情
表情消息
baseURL 拼接图片文件名,表情图片Asset路径
通过路径,解析 Asset 资源
图片资源预存于Asset,并定义 List
-



现在,我们就来动手接入TUIKit 的表情能力。
说明
TUIKit 在升级至1.1.0版本后,对表情能力用法有较大改动。请您在升级最新版后,根据本文档指引,重新适配接入表情能力。谢谢~

STEP1: 自定义表情图片资源

说明
本步骤选做: 如果您需要用到非默认提供的 QQ 小表情外的其他图片表情,如自定义图片小表情及图片大表情,才需完成本步骤。 QQ 小表情包,TUIKit 已自带提供,无需在本步骤引入,请关注后续步骤。

将文件导入项目

请将您的表情资源文件,导入项目的 assets/custom_face_resource/ 目录内。无论是图片大表情,抑或是图片小表情,都需按此步骤引入。
该目录内,请使用不同的文件夹,区分表情面板中的不同 Tab。每个 Tab 内表情,仅支持一种类型,图片大表情或图片小表情。
文件夹的名称,请使用该 Tab 的 name 命名。该命名不会对客户展现,请根据开发需要,自定义即可。
请保证,所有表情资源文件,不要重名。
此路径的表情图片放置引入,可参考我们的 Demo




声明表情文件

打开 pubspec.yaml 文件,在 flutter => assets 中,声明刚刚引入的表情资源文件。
flutter:
assets:
- assets/custom_face_resource/

在代码中配置图片资源List

说明
本步骤代码示例请参考此处,直接看 emojiList 即可。
在您代码定义静态参数或配置的地方,定义一个 static List<CustomEmojiFaceData>,用于将本地图片资源,转换成 TUIKit 可以接受的格式,后续以 List 方式传入。
List 中,每个 item 都是 CustomEmojiFaceData,每个 CustomEmojiFaceData 构成一个表情面板中的 Tab。具体参数说明如下:
CustomEmojiFaceData(
{
String name, // 文件夹目录名称
String icon, // Tab中的icon资源文件名
List<String> list, // 每个图片的文件名,以List
bool isEmoji // 是否为图片小表情,默认为false,即图片大表情
}
);
示例代码如下:
static final List<CustomEmojiFaceData> emojiList = [
// 使用图片小表情,支持图文混排,以文本消息形式发送
CustomEmojiFaceData(
name: '4349',
icon: "aircraft.png",
isEmoji: true,
list: [
"aircraft.png",
"alarmClock.png",
"anger.png",
// ...
]),

// 使用图片大表情,不支持图文混排,以表情消息形式发送
CustomEmojiFaceData(
name: '4350',
icon: "menu@2x.png",
list: [
"yz00@2x.png",
// ...
]),
]

STEP2: 自定义 Emoji Unicode 字符串 List

说明
本步骤选做: 如果您需要用到 Unicode Emoji 表情,才需完成本步骤。
在您代码定义静态参数或配置的地方,定义一个 List<Map<String, Object>> Unicode 列表,供传入。
该列表,我们提供一套示例,在附录中。
您看直接复制引入这套示例列表,或基于此修改。

STEP3: 表情资源预读入内存

说明
本步骤代码示例请参考此处,直接看 setCustomSticker 方法即可。 QQ 小表情包,TUIKit 已自带提供,无需在本步骤引入,请关注后续步骤。
在您的项目启动后,首个 TIMUIKitChat 组件渲染前,将上一步定义的图片表情资源 List,转换成 TUIKit 表情的实例,放入全局 Provider 中,存储于内存里。
本步骤方法仅需执行一次,一次性全部读入内存中。 因展示渲染表情资源为高频操作,如每次展示前才动态读入内存,对资源与性能占用比较大。
单个表情内存实例,使用 CustomSticker 类生成。如果传入了 unicode 则为 Unicode Emoji 表情,否则为图片类型表情。
class CustomSticker {
int? unicode; // Unicode int值。如果传入了 `unicode` 则为 Unicode Emoji表情,否则为图片类型表情
String name; // 表情名称
int index; // 表情序号
bool isEmoji; // 是否为图片小表情,默认为图片大表情
}
每个 Tab 的内存实例,使用 CustomStickerPackage 类生成。
class CustomStickerPackage { // 一个系列的表情包定义为一个package,占据一个表情面板Tab
String name; // 表情包package name,该Tab文件夹名称。
String? baseUrl; // 表情包package baseUrl,建议配置成:"assets/custom_face_resource/${表情包文件夹名称 即 表情包package name}"
List<CustomSticker> stickerList; // 表情资源列表
CustomSticker menuItem; // 表情面包Tab按钮icon
bool isEmoji; // 是否为图片小表情,默认为图片大表情
}
综上所述,需要写的代码,我们给出示例版本。
表情项一演示如何使用 Emoji Unicode 表情包,表情项二演示如何使用图片类型(包含大或小)表情包。您可以根据需要,使用全部或部分代码。
setCustomSticker() async {
// 定义一个大List来承载各个表情包 package Tab
List<CustomStickerPackage> customStickerPackageList = [];

// 表情项一:使用Emoji Unicode表情列表。可以嵌入文字内容中。
// `emojiData` 来自于STEP2。
final defEmojiList = emojiData.asMap().keys.map((emojiIndex) {
final emoji = Emoji.fromJson(emojiData[emojiIndex]);
return CustomSticker(
index: emojiIndex, name: emoji.name, unicode: emoji.unicode);
}).toList();
customStickerPackageList.add(CustomStickerPackage(
name: "defaultEmoji",
stickerList: defEmojiList,
menuItem: defEmojiList[0]));

// 表情项二:使用您提供的图片表情包。
// 务必保证 `customEmojiPackage.name` 为该Tab文件夹名称。
// `Const.emojiList` 来自于STEP1。
customStickerPackageList.addAll(Const.emojiList.map((customEmojiPackage) {
return CustomStickerPackage(
name: customEmojiPackage.name,
baseUrl: "assets/custom_face_resource/${customEmojiPackage.name}",
stickerList: customEmojiPackage.list
.asMap()
.keys
.map((idx) =>
CustomSticker(index: idx, name: customEmojiPackage.list[idx]))
.toList(),
menuItem: CustomSticker(
index: 0,
name: customEmojiPackage.icon,
));
}).toList());

Provider.of<CustomStickerPackageData>(context, listen: false)
.customStickerPackageList = customStickerPackageList;
}

STEP4: 为 TIMUIKitChat 组件添加表情解析能力

说明
本步骤代码示例请参考此处,重点浏览 renderCustomStickerPanel, customStickerPanelcustomEmojiList 即可。
将以下代码,直接拷贝进入您用于承载 TIMUIKitChat 组件的类中。
Widget renderCustomStickerPanel({
sendTextMessage,
sendFaceMessage,
deleteText,
addCustomEmojiText,
addText,
List<CustomEmojiFaceData> defaultCustomEmojiStickerList = const [],
}) {
final theme = Provider.of<DefaultThemeData>(context).theme;
final customStickerPackageList =
Provider.of<CustomStickerPackageData>(context).customStickerPackageList;
final defaultEmojiList =
defaultCustomEmojiStickerList.map((customEmojiPackage) {
return CustomStickerPackage(
name: customEmojiPackage.name,
baseUrl: "assets/custom_face_resource/${customEmojiPackage.name}",
isEmoji: customEmojiPackage.isEmoji,
isDefaultEmoji: true,
stickerList: customEmojiPackage.list
.asMap()
.keys
.map((idx) =>
CustomSticker(index: idx, name: customEmojiPackage.list[idx]))
.toList(),
menuItem: CustomSticker(
index: 0,
name: customEmojiPackage.icon,
));
}).toList();
return StickerPanel(
sendTextMsg: sendTextMessage,
sendFaceMsg: (index, data) =>
sendFaceMessage(index + 1, (data.split("/")[3]).split("@")[0]),
deleteText: deleteText,
addText: addText,
addCustomEmojiText: addCustomEmojiText,
customStickerPackageList: [
...defaultEmojiList,
...customStickerPackageList
],
backgroundColor: theme.weakBackgroundColor,
lightPrimaryColor: theme.lightPrimaryColor);
}

STEP4.1: 渲染图片小表情

本步骤选做:
如果您的项目需要用到图片小表情,包括自定义图片小表情,或直接使用默认自带 QQ 同款图片小表情,才需完成本步骤。
图片小表情展现形式和 Unicode Emoji 类似,建议 Unicode Emoji 和图片小表情选用一个即可。即,如果您选用了 Unicode Emoji,可直接跳过本步骤。
STEP4.1(a) 为使用自定义图片小表情;
STEP4.1(b) 为使用默认自带 QQ 同款图片小表情。
以上方案,建议直接选用一个方案即可。
如果需要同时使用,请保证您的自定义图片小表情名称,不要和我们默认提供的 QQ 同款图片小表情重复。

STEP4.1(a): 添加渲染解析自定义图片小表情的支持

在您用于承载 TIMUIKitChat 组件的 build 方法中,定义一个 List customEmojiList 变量,用于存放图片小表情列表。
List customEmojiList =
Const.emojiList.where((element) => element.isEmoji == true).toList();
并将此列表,传入 TIMUIKitChat 组件的 customEmojiStickerList 参数内。
return TIMUIKitChat(
customEmojiStickerList: customEmojiList,
// ......
);
说明
如果您用于承载 TIMUIKitChat 组件的类为 StatefulWidget,您可将 customEmojiList 变量,放入 State 中,仅在首次 build 时,才去执行 where 命令,优化性能。

STEP4.1(b): 启用 QQ 小表情包

TIMUIKitChatTIMUIKitChatConfigisUseDefaultEmoji 参数,设置为 true 即可。此时,会向表情包面板最左侧,自动生成一个承载 QQ 小表情包的 Tab。
return TIMUIKitChat(
config: TIMUIKitChatConfig(
isUseDefaultEmoji: true,
// ......
),
// ......
);




STEP4.2: 将表情包能力,注入 TIMUIKitChat

将本步骤最开始让您复制的代码方法,传入 TIMUIKitChat 组件的 customStickerPanel 参数内。
return TIMUIKitChat(
customStickerPanel: renderCustomStickerPanel,
// ......
);
此时,TUIKit 表情能力接入完成。您可正常收发测试。如在接入过程中,有任何问题,欢迎随时联系我们

附录: Emoji Unicode 列表示例

本列表仅用于示例演示,您可根据需要,增加或修改。
List<Map<String, Object>> emojiData = [
{"name": "GRINNING FACE WITH SMILING EYES", "unicode": 128513},
{"name": "FACE WITH TEARS OF JOY", "unicode": 128514},
{"name": "SMILING FACE WITH OPEN MOUTH", "unicode": 128515},
{"name": "SMILING FACE WITH OPEN MOUTH AND SMILING EYES", "unicode": 128516},
{"name": "SMILING FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128517},
{
"name": "SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES",
"unicode": 128518
},
{"name": "WINKING FACE", "unicode": 128521},
{"name": "SMILING FACE WITH SMILING EYES", "unicode": 128522},
{"name": "FACE SAVOURING DELICIOUS FOOD", "unicode": 128523},
{"name": "RELIEVED FACE", "unicode": 128524},
{"name": "SMILING FACE WITH HEART-SHAPED EYES", "unicode": 128525},
{"name": "SMIRKING FACE", "unicode": 128527},
{"name": "UNAMUSED FACE", "unicode": 128530},
{"name": "FACE WITH COLD SWEAT", "unicode": 128531},
{"name": "PENSIVE FACE", "unicode": 128532},
{"name": "CONFOUNDED FACE", "unicode": 128534},
{"name": "FACE THROWING A KISS", "unicode": 128536},
{"name": "KISSING FACE WITH CLOSED EYES", "unicode": 128538},
{"name": "FACE WITH STUCK-OUT TONGUE AND WINKING EYE", "unicode": 128540},
{
"name": "FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES",
"unicode": 128541
},
{"name": "DISAPPOINTED FACE", "unicode": 128542},
{"name": "ANGRY FACE", "unicode": 128544},
{"name": "POUTING FACE", "unicode": 128545},
{"name": "CRYING FACE", "unicode": 128546},
{"name": "PERSEVERING FACE", "unicode": 128547},
{"name": "FACE WITH LOOK OF TRIUMPH", "unicode": 128548},
{"name": "DISAPPOINTED BUT RELIEVED FACE", "unicode": 128549},
{"name": "FEARFUL FACE", "unicode": 128552},
{"name": "WEARY FACE", "unicode": 128553},
{"name": "SLEEPY FACE", "unicode": 128554},
{"name": "TIRED FACE", "unicode": 128555},
{"name": "LOUDLY CRYING FACE", "unicode": 128557},
{"name": "FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128560},
{"name": "FACE SCREAMING IN FEAR", "unicode": 128561},
{"name": "ASTONISHED FACE", "unicode": 128562},
{"name": "FLUSHED FACE", "unicode": 128563},
{"name": "DIZZY FACE", "unicode": 128565},
{"name": "FACE WITH MEDICAL MASK", "unicode": 128567},
{"name": "GRINNING CAT FACE WITH SMILING EYES", "unicode": 128568},
{"name": "CAT FACE WITH TEARS OF JOY", "unicode": 128569},
{"name": "SMILING CAT FACE WITH OPEN MOUTH", "unicode": 128570},
{"name": "SMILING CAT FACE WITH HEART-SHAPED EYES", "unicode": 128571},
{"name": "CAT FACE WITH WRY SMILE", "unicode": 128572},
{"name": "KISSING CAT FACE WITH CLOSED EYES", "unicode": 128573},
{"name": "POUTING CAT FACE", "unicode": 128574},
{"name": "CRYING CAT FACE", "unicode": 128575},
{"name": "WEARY CAT FACE", "unicode": 128576},
{"name": "FACE WITH NO GOOD GESTURE", "unicode": 128581},
{"name": "FACE WITH OK GESTURE", "unicode": 128582},
{"name": "PERSON BOWING DEEPLY", "unicode": 128583},
{"name": "SEE-NO-EVIL MONKEY", "unicode": 128584},
{"name": "HEAR-NO-EVIL MONKEY", "unicode": 128585},
{"name": "SPEAK-NO-EVIL MONKEY", "unicode": 128586},
{"name": "HAPPY PERSON RAISING ONE HAND", "unicode": 128587},
{"name": "PERSON RAISING BOTH HANDS IN CELEBRATION", "unicode": 128588},
{"name": "PERSON FROWNING", "unicode": 128589},
{"name": "PERSON WITH POUTING FACE", "unicode": 128590},
{"name": "PERSON WITH FOLDED HANDS", "unicode": 128591},
{"name": "BLACK SCISSORS", "unicode": 9986},
{"name": "WHITE HEAVY CHECK MARK", "unicode": 9989},
{"name": "AIRPLANE", "unicode": 9992},
{"name": "ENVELOPE", "unicode": 9993},
{"name": "RAISED FIST", "unicode": 9994},
{"name": "RAISED HAND", "unicode": 9995},
{"name": "VICTORY HAND", "unicode": 9996},
{"name": "PENCIL", "unicode": 9999},
{"name": "BLACK NIB", "unicode": 10002},
{"name": "HEAVY CHECK MARK", "unicode": 10004},
{"name": "HEAVY MULTIPLICATION X", "unicode": 10006},
{"name": "SPARKLES", "unicode": 10024},
{"name": "EIGHT SPOKED ASTERISK", "unicode": 10035},
{"name": "EIGHT POINTED BLACK STAR", "unicode": 10036},
{"name": "SNOWFLAKE", "unicode": 10052},
{"name": "SPARKLE", "unicode": 10055},
{"name": "CROSS MARK", "unicode": 10060},
{"name": "NEGATIVE SQUARED CROSS MARK", "unicode": 10062},
{"name": "BLACK QUESTION MARK ORNAMENT", "unicode": 10067},
{"name": "WHITE QUESTION MARK ORNAMENT", "unicode": 10068},
{"name": "WHITE EXCLAMATION MARK ORNAMENT", "unicode": 10069},
{"name": "HEAVY EXCLAMATION MARK SYMBOL", "unicode": 10071},
{"name": "HEAVY BLACK HEART", "unicode": 10084},
{"name": "HEAVY PLUS SIGN", "unicode": 10133},
{"name": "HEAVY MINUS SIGN", "unicode": 10134},
{"name": "HEAVY DIVISION SIGN", "unicode": 10135},
{"name": "BLACK RIGHTWARDS ARROW", "unicode": 10145},
{"name": "CURLY LOOP", "unicode": 10160},
{"name": "ROCKET", "unicode": 128640},
{"name": "RAILWAY CAR", "unicode": 128643},
{"name": "HIGH-SPEED TRAIN", "unicode": 128644},
{"name": "HIGH-SPEED TRAIN WITH BULLET NOSE", "unicode": 128645},
{"name": "METRO", "unicode": 128647},
{"name": "STATION", "unicode": 128649},
{"name": "BUS", "unicode": 128652},
{"name": "BUS STOP", "unicode": 128655},
{"name": "AMBULANCE", "unicode": 128657},
{"name": "FIRE ENGINE", "unicode": 128658},
{"name": "POLICE CAR", "unicode": 128659},
{"name": "TAXI", "unicode": 128661},
{"name": "AUTOMOBILE", "unicode": 128663},
{"name": "RECREATIONAL VEHICLE", "unicode": 128665},
{"name": "DELIVERY TRUCK", "unicode": 128666},
{"name": "SHIP", "unicode": 128674},
{"name": "SPEEDBOAT", "unicode": 128676},
{"name": "HORIZONTAL TRAFFIC LIGHT", "unicode": 128677},
{"name": "CONSTRUCTION SIGN", "unicode": 128679},
{"name": "POLICE CARS REVOLVING LIGHT", "unicode": 128680},
{"name": "TRIANGULAR FLAG ON POST", "unicode": 128681},
{"name": "DOOR", "unicode": 128682},
{"name": "NO ENTRY SIGN", "unicode": 128683},
{"name": "SMOKING SYMBOL", "unicode": 128684},
{"name": "NO SMOKING SYMBOL", "unicode": 128685},
{"name": "BICYCLE", "unicode": 128690},
{"name": "PEDESTRIAN", "unicode": 128694},
{"name": "MENS SYMBOL", "unicode": 128697},
{"name": "WOMENS SYMBOL", "unicode": 128698},
{"name": "RESTROOM", "unicode": 128699},
{"name": "BABY SYMBOL", "unicode": 128700},
{"name": "TOILET", "unicode": 128701},
{"name": "WATER CLOSET", "unicode": 128702},
{"name": "BATH", "unicode": 128704},
{"name": "CIRCLED LATIN CAPITAL LETTER M", "unicode": 9410},
{"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER A", "unicode": 127344},
{"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER B", "unicode": 127345},
{"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER O", "unicode": 127358},
{"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER P", "unicode": 127359},
{"name": "NEGATIVE SQUARED AB", "unicode": 127374},
{"name": "SQUARED CL", "unicode": 127377},
{"name": "SQUARED COOL", "unicode": 127378},
{"name": "SQUARED FREE", "unicode": 127379},
{"name": "SQUARED ID", "unicode": 127380},
{"name": "SQUARED NEW", "unicode": 127381},
];

联系我们

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