跳到主要内容

Emoji 与贴纸表情

用户可以 IMKit 输入区域发送 Emoji 表情、贴纸表情。点击输入栏的表情(☺)按钮,即可展开表情面板,支持发送 Emoji 表情、贴纸表情。表情消息将出现在会话页面的消息列表组件中。

提示

IMKit 输入区域的表情面板中默认仅包含 emoji。支持添加自定义表情。

Emoji 符号表情

IMKit 输入区域的表情面板中默认展示内置 Emoji 符号表情。用户点击后可发送 Emoji 符号表情。

禁用表情面板中的内置 Emoji 表情

从 1.5.1 版本开始支持。实现 IExtensionConfig,创建自定义的扩展面板配置类,重写 getEmoticonTabs() 方法。getEmoticonTabs 不返回 SDK 内置表情组件 EmojiTab 即可。参照动态配置表情面板

自定义表情组件

从 1.5.1 版本开始,IMKit 支持自定义表情组件。

添加自定义表情组件

以下步骤介绍了如何将自定义贴纸表情加入表情面板。

  1. 创建 MyEmoticonTab 实现 IEmoticonTab
TypeScript
export class MyEmoticonTab extends IEmoticonTab {
obtainTabName(): string {
return "MyEmoticonTab"
}

obtainTabDrawable(context: Context): ResourceStr {
return $r("app.media.rc_custom_emoji_icon")
}

obtainTabPager(context: Context): WrappedBuilder<[Context, ConversationIdentifier, IEmoticonTab]> {
return wrapBuilder(buildCustomEmoticonSwiperPageView)
}

onTableSelected(context: Context, index: number): void {
console.log("index:" + index)
}
}
  1. 在上方的 obtainTabPager 方法中添加想要展示在表情面板上的 View。下方提供了一个比较完整的参考示例:
TypeScript
@Builder
export function buildCustomEmoticonSwiperPageView(context: Context, convId: ConversationIdentifier, tab: IEmoticonTab) {
CustomEmoticonSwiperPage({ convId: convId, tab: tab })
}

class CustomDataSource implements IDataSource {
private list: EmojiData[][] = []

constructor(list: EmojiData[][]) {
this.list = list
}

totalCount(): number {
return this.list.length
}

getData(index: number): EmojiData[] {
return this.list[index]
}

registerDataChangeListener(listener: DataChangeListener): void {
}

unregisterDataChangeListener() {
}
}

class EmojiData {
// emoji图标的资源地址,可以是本地路径,
public emojiUrl: string = "";
// emoji名字
public name: string = "";

constructor(emojiUrl: string, name: string) {
this.emojiUrl = emojiUrl;
this.name = name;
}
}

@Component
export struct CustomEmoticonSwiperPage {
@Require @Prop tab: IEmoticonTab;
@Require @Prop convId: ConversationIdentifier;
private customDataSource: CustomDataSource = new CustomDataSource([])

aboutToAppear(): void {
// 这里是示例,实际数据源需要业务侧处理
let emojiData: EmojiData[] = [
new EmojiData("1.png", "圣诞树"),
new EmojiData("2.png", "玫瑰"),
new EmojiData("3.png", "西瓜"),
new EmojiData("4.png", "烤肉"),
new EmojiData("5.png", "冰淇淋"),
new EmojiData("6.png", "红酒"),
new EmojiData("7.png", "礼物"),
new EmojiData("8.png", "蛋糕"),
new EmojiData("9.png", "圣诞树"),
new EmojiData("10.png", "庆祝"),
new EmojiData("11.png", "博士"),
new EmojiData("12.png", "骏马"),
new EmojiData("13.png", "小狗"),
new EmojiData("14.png", "猪头"),
new EmojiData("15.png", "皇冠"),
new EmojiData("16.png", "火苗")]
let dataList: EmojiData[][] = []
for (let i = 0; i <= 8; i += 8) {
const emojisSubset = emojiData.slice(i, i + 8);
dataList.push(emojisSubset)
}
this.customDataSource = new CustomDataSource(dataList)
}

build() {
Swiper() {
LazyForEach(this.customDataSource, (item: EmojiData[]) => {
this.emojiPageView(item)
}, (item: string[]) => item.toString())
}
.loop(false)
.indicator(
new DotIndicator().itemWidth(8)
.itemHeight(8)
.selectedItemWidth(9)
.selectedItemHeight(9)
.color(Color.Gray)
.selectedColor(Color.Black)
)
.onChange((index: number) => {
console.info(index.toString())
})
.width('100%')
.layoutWeight(1)
.nestedScroll(SwiperNestedScrollMode.SELF_FIRST)
}

@Builder
emojiPageView(pageData: EmojiData[]) {
Column() {
Grid() {
ForEach(pageData, (item: EmojiData) => {
GridItem() {
Column() {
Image(item.emojiUrl).width(40).height(40)
Text(item.name).fontSize(12)
}
}.onClick(() => {
// 可以监听点击事件,做发送消息的操作
})
})
}.columnsTemplate('1fr 1fr 1fr 1fr').rowsTemplate('1fr 1fr').width('100%').height('100%')
}.width('100%').height('100%').padding({ bottom: 20 })
}

}
  1. 添加自定义表情组件
TypeScript
RongExtensionManager.getInstance().addEmoticonTab(new MyEmoticonTab())

除了添加自定义表情,还支持移除自定义表情组件、清除所有自定义表情组件、获取所有添加的自定义表情组件列表:

TypeScript
// 移除自定义表情组件
RongExtensionManager.getInstance().removeEmoticonTabByName("MyEmoticonTab")

// 清除所有自定义表情组件
RongExtensionManager.getInstance().clearAllEmoticonTab()

// 获取所有添加的自定义表情组件列表
let tabList:List<IEmoticonTab> = RongExtensionManager.getInstance().getEmoticonTabList()

动态配置表情面板

如果应用程序需要动态添加、删除表情面板表情,或者调整自定义表情位置,建议通过创建自定义的表情面板配置实现这些自定义需求。

实现 IExtensionConfig,创建自定义的扩展面板配置类,重写 getEmoticonTabs() 方法。您可以增加或删除扩展项,也可以调整各个表情组件的位置。

TypeScript
import { EmojiTab, EmojiIEmoticonTabTabName } from '@rongcloud/imkit';

let mCustomExtensionConfig: IExtensionConfig = {
getEmoticonTabs: (convId: ConversationIdentifier) => {
let tabs: ArrayList<IEmoticonTab> = new ArrayList<IEmoticonTab>();
// EmojiTab 是 SDK 内置的 emoji Tab
tabs.add(new EmojiTab())
// getEmoticonTabList获取当前设置的 Tab 列表
let tabList = RongIM.getInstance().conversationService().getEmoticonTabList()
// 可以调整顺序、添加或者移除。
for (let tab of tabList) {
tabs.add(tab)
}
return tabs
}
}

SDK 初始化之后,调用以下方法设置自定义的输入配置,SDK 会根据此配置展示扩展面板。

TypeScript
RongIM.getInstance().conversationService().setExtensionConfig(mCustomExtensionConfig)

获取当前插件配置

TypeScript
let config = RongExtensionManager.getInstance().getExtensionConfig()
// 根据 ConversationIdentifier 获取对应的插件列表
let convId: ConversationIdentifier
let pluginModules = config.getEmoticonTabs(convId)

隐藏表情面板入口

IMKit SDK 暂时还不支持此功能。

自定义表情面板添加按钮

从 1.5.1 版本开始,IMKit 默认允许配置会话页面输入框的一些UI组件。可通过 setInputAreaComponentConfig(InputAreaComponentConfig) 接口设置自定义组件配置。 默认该组件不展示。

TypeScript
export interface InputAreaComponentConfig {
/**
* 组件标识
*/
identifier: ComponentIdentifier,
/**
* 组件WrappedBuilder
*/
component?: WrappedBuilder<[InputAreaComponentData]> | null,
}

/**
* 输入区域自定义组件数据,封装必要的参数透传给自定义组件
* @since 1.6.0
*/
export class InputAreaComponentData {
/**
* 上下文
*/
context: Context | undefined;
/**
* 会话标识
*/
convId: ConversationIdentifier | undefined;
/**
* 透传参数
*
*```
* 当 `identifier` 为某些枚举类型的情况下有值,其余情况下为空。详细说明如下
* 1. ComponentIdentifier.InputBarVoiceButton: "Voice" 语音类型、"Text" 文本类型。
* 2. ComponentIdentifier.InputBarEmoticonButton: "Emoticon" 表情类型、"Text" 文本类型。
* 3. ComponentIdentifier.DestructBarVoiceButton: "Voice" 语音类型、"Text" 文本类型。
*```
*/
data: string = "";
}

identifier 支持的组件类型说明:

组件类型说明
EmoticonBoardAddButton表情面板左下角的添加按钮

component 说明: WrappedBuilder 第三个参数返回空。

TypeScript
// 设置接口
let EmoticonBoardAddButton: InputAreaComponentConfig = {
identifier: ComponentIdentifier.EmoticonBoardAddButton,
component: wrapBuilder(buildCustomEmoticonBoardAddButtonView),
}
RongIM.getInstance().conversationService().setInputAreaComponentConfig(EmoticonBoardAddButton)

// 组件
@Builder
export function buildCustomEmoticonBoardAddButtonView(componentData: InputAreaComponentData) {
CustomEmoticonBoardAddButtonView({ context: componentData.context, convId: componentData.convId })
}

@Component
export struct CustomEmoticonBoardAddButtonView {
@Prop context: Context;
@Prop convId: ConversationIdentifier;

build() {
Row() {
Button({ type: ButtonType.Normal }) {
Image($r('app.media.seal_ic_main_more')).size({ width: 20, height: 20 })
}
.width('60').height('36')
.backgroundColor($r('app.color.rc_color_00000000')).onClick(() => {
// 点击事件
})
}
}
}