说明:
腾讯云 IM Fluter UIKit 接入表情能力,已在2.2.0版本得到大幅优化。用法简单清晰许多,只要简单传入配置项,即可快速启用。不再需要使用本文的
所述的用法,写大量兼容代码。
以下为您介绍,如何为腾讯云 IM Flutter TUIKit 引入表情能力。
我们的
TIMUIKitChat
组件中,支持发送及接收三种类型的表情:
现在,我们就来动手接入TUIKit 的表情能力。
说明
STEP1: 自定义表情图片资源
说明
本步骤选做:
如果您需要用到非默认提供的 QQ 小表情外的其他图片表情,如自定义图片小表情及图片大表情,才需完成本步骤。
QQ 小表情包,TUIKit 已自带提供,无需在本步骤引入,请关注后续步骤。
将文件导入项目
请将您的表情资源文件,导入项目的
assets/custom_face_resource/
目录内。无论是图片大表情,抑或是图片小表情,都需按此步骤引入。该目录内,请使用不同的文件夹,区分表情面板中的不同 Tab。每个 Tab 内表情,仅支持一种类型,图片大表情或图片小表情。
文件夹的名称,请使用该 Tab 的
name
命名。该命名不会对客户展现,请根据开发需要,自定义即可。请保证,所有表情资源文件,不要重名。
声明表情文件
打开
pubspec.yaml
文件,在 flutter
=> assets
中,声明刚刚引入的表情资源文件。flutter:assets:- assets/custom_face_resource/
在代码中配置图片资源List
说明
在您代码定义静态参数或配置的地方,定义一个
static List<CustomEmojiFaceData>
,用于将本地图片资源,转换成 TUIKit 可以接受的格式,后续以 List
方式传入。此
List
中,每个 item 都是 CustomEmojiFaceData
,每个 CustomEmojiFaceData
构成一个表情面板中的 Tab。具体参数说明如下:CustomEmojiFaceData({String name, // 文件夹目录名称String icon, // Tab中的icon资源文件名List<String> list, // 每个图片的文件名,以Listbool 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
说明
在您代码定义静态参数或配置的地方,定义一个
List<Map<String, Object>>
Unicode 列表,供传入。您看直接复制引入这套示例列表,或基于此修改。
STEP3: 表情资源预读入内存
说明
在您的项目启动后,首个
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,占据一个表情面板TabString name; // 表情包package name,该Tab文件夹名称。String? baseUrl; // 表情包package baseUrl,建议配置成:"assets/custom_face_resource/${表情包文件夹名称 即 表情包package name}"List<CustomSticker> stickerList; // 表情资源列表CustomSticker menuItem; // 表情面包Tab按钮iconbool isEmoji; // 是否为图片小表情,默认为图片大表情}
综上所述,需要写的代码,我们给出示例版本。
表情项一演示如何使用 Emoji Unicode 表情包,表情项二演示如何使用图片类型(包含大或小)表情包。您可以根据需要,使用全部或部分代码。
setCustomSticker() async {// 定义一个大List来承载各个表情包 package TabList<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 组件添加表情解析能力
说明
将以下代码,直接拷贝进入您用于承载
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 小表情包
将
TIMUIKitChat
的 TIMUIKitChatConfig
的 isUseDefaultEmoji
参数,设置为 true
即可。此时,会向表情包面板最左侧,自动生成一个承载 QQ 小表情包的 Tab。return TIMUIKitChat(config: TIMUIKitChatConfig(isUseDefaultEmoji: true,// ......),// ......);
STEP4.2: 将表情包能力,注入 TIMUIKitChat
将本步骤最开始让您复制的代码方法,传入
TIMUIKitChat
组件的 customStickerPanel
参数内。return TIMUIKitChat(customStickerPanel: renderCustomStickerPanel,// ......);
附录: 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},];