HarmonyOS鸿蒙开发实战(5.0)表情图片聊天案例实践

鸿蒙HarmonyOS NEXT开发实战往期文章必看(持续更新......)

HarmonyOS NEXT应用开发性能实践总结

HarmonyOS NEXT应用开发案例实践总结合集

最新版!“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通)

非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!


介绍

本示例主要介绍如何在聊天信息中加入表情图片。通过变量控制表情键盘的显示与否,使用RichEdit接收所选表情的ImageSpan。在发送信息时将图片和文字消息分别通过ImageSpan、Span加入到消息列表中,显示的时候将消息列表中的ImageSpan、Span包裹在Text中进行显示,同时实现了最近使用表情和长按表情图片弹窗显示表情明细的效果。

效果图预览

使用说明

  1. 进入页面,在底部输入框中输入文字,点击输入框右边的表情图片按钮弹出表情键盘,长按表情图片弹窗显示表情明细。在表情键盘中选择表情图片后点击发送,在聊天对话框中会显示聊天文字以及表情。

实现思路

  1. 将实现了Popup效果的单个表情功能封装成EmojiDetail自定义组件。选中表情图片后,将表情通过imageSpan的方式加到RichEditor输入框中,同时加入到最近使用的表情数据列表中。源码参考EmojiDetail.ets

    Image(this.EmojiItem!.imgSrc).width(FaceGridConstants.EMOJI_IMAGE_SIZE).height(FaceGridConstants.EMOJI_IMAGE_SIZE).onClick(() => {// TODO 知识点:将表情添加到输入框中this.controllerRich!.addImageSpan(this.EmojiItem!.imgSrc, {imageStyle: {size: [this.msgFontSize / 3.2, this.msgFontSize / 3.2], // 3.2 调整表情在输入框中的尺寸verticalAlign: ImageSpanAlignment.CENTER}});// TODO 知识点:将表情添加到最近使用表情中this.lastEmojiData.pushData(this.EmojiItem!);}).draggable(false).gesture(// TODO 知识点:长按弹出表情明细LongPressGesture().onAction(() => {this.isPopup = true;}).onActionEnd(() => {this.isPopup = false;})).bindPopup(this.isPopup, {// TODO 知识点:使用bindPopup弹出表情明细builder: this.popupBuilder, onStateChange: (e) => {if (!e.isVisible) {this.isPopup = false;}}})
    
  2. 使用Grid和EmojiDetail自定义组件创建表情键盘,源码参考EmojiKeyboard.ets

    Grid() {// TODO: 性能知识点:使用ForEach组件循环渲染数据ForEach(this.emojiList, (item: EmojiModel) => {GridItem() {// 表情明细组件EmojiDetail({controllerRich: this.controllerRich,EmojiItem: item,msgFontSize: this.msgFontSize,lastEmojiData: this.lastEmojiData})}})
    }
    .maxCount(FaceGridConstants.GRID_MAX_COUNT)
    .columnsTemplate("1fr 1fr 1fr 1fr 1fr 1fr") // 分成6份
    .rowsGap(FaceGridConstants.ROWS_GAP)
    
  3. 点击表情按钮时弹出最近表情和全部表情键盘,源码参考ChatWithExpression.ets

    // TODO 知识点:通过变量控制表情键盘的显示
    if (this.isFaceDlgOpen) {Column() {// 最近使用的表情if (this.lastEmojiData.totalCount() > 0) {Text($r('app.string.chat_with_expression_last_emoji')).alignSelf(ItemAlign.Start).margin($r('app.integer.chat_with_expression_chat_margin_top'))// 表情键盘组件Emojikeyboard({controllerRich: this.controllerRich,msgFontSize: this.msgFontSize,lastEmojiData: this.lastEmojiData,emojiList: this.lastEmojiData.emojiList})}// 全部表情Text($r('app.string.chat_with_expression_all_emoji')).alignSelf(ItemAlign.Start).margin($r('app.integer.chat_with_expression_chat_margin_top'))// 表情键盘组件Emojikeyboard({controllerRich: this.controllerRich,msgFontSize: this.msgFontSize,lastEmojiData: this.lastEmojiData,emojiList: EmojiData})}
    }
    
  4. 点击发送时,通过RichEditorController的getSpans方法,将聊天信息中ImageSpan、Span分别push到要发送的信息的spanItems中。源码参考ChatWithExpression.ets的sendChatMsg方法

    let msgBase = new MessageBase(true, USER_NAME_MYSELF, HEAD_IMAGE_MYSELF, this.msgMaxWidth);
    // 获取发送信息
    this.controllerRich.getSpans({start: this.start,end: this.end
    }).forEach(item => {if (typeof (item as RichEditorImageSpanResult)['imageStyle'] !== 'undefined') {// TODO 知识点:处理imagespan信息const imageMsg: ResourceStr | undefined = (item as RichEditorImageSpanResult).valueResourceStr;if (imageMsg !== undefined) {const spanItem: SpanItem = new SpanItem(SpanType.IMAGE, '', imageMsg.toString().substring(EMOJI_SRC_POS));msgBase.spanItems.push(spanItem);}} else {// TODO 知识点:处理文字span信息const textMsg: string = (item as RichEditorTextSpanResult).value;const spanItem: SpanItem = new SpanItem(SpanType.TEXT, textMsg, '');msgBase.spanItems.push(spanItem);}
    })
    logger.info(TAG, 'sendChatMsg spanItems:' + msgBase.spanItems.length.toString());
    // 发送
    if (msgBase.spanItems.length !== 0) {this.textDetailData.pushData(msgBase);this.msgNums = this.textDetailData.totalCount();this.scroller.scrollToIndex(this.msgNums - 1);this.controllerRich.deleteSpans();this.controllerRich.setCaretOffset(-1);
    }
    this.customFaceDialogCtl.close();
    this.isFaceDlgOpen = false;
    this.marginBottomInput = 0;
    focusControl.requestFocus(this.focusKey);
    
  5. 在聊天对话框中通过LazyForEach循环加载聊天信息。

    // 聊天对话框
    List({scroller: this.scroller,initialIndex: this.msgNums - 1
    }) {// 性能知识点:使用懒加载组件渲染数据。参考资料:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-lazyforeach-0000001820879609LazyForEach(this.textDetailData, (msg: MessageBase) => {ListItem() {if (msg.isSelf) {MessageItemSelfView({ msg: msg });} else {MessageItemView({ msg: msg });}}})
    }
    
  6. 将聊天信息的SpanItems根据spanType在Text中分别包裹为ImageSpan跟Span。

    // 聊天信息
    Row() {Text(undefined) {// TODO: 性能知识点:使用ForEach组件循环渲染数据ForEach(this.msg.spanItems, (item: SpanItem) => {// TODO 知识点:分别使用ImageSpan、Span渲染图片、文字信息if (item.spanType === SpanType.IMAGE) {ImageSpan($rawfile(item.imgSrc as string)).width($r('app.integer.chat_font_size')).height($r('app.integer.chat_font_size')).verticalAlign(ImageSpanAlignment.BOTTOM).objectFit(ImageFit.Cover)} else if (item.spanType === SpanType.TEXT) {Span(item.text)}})}.constraintSize({minHeight: $r('app.integer.chat_inline_height'),maxWidth: this.msg.maxWidth}).textAlign(TextAlign.Start)
    }
    

高性能知识点

本示例使用了LazyForEach进行数据懒加载,同时搭配组件复用能力以达到性能最优效果。

工程结构&模块类型

chatwithexpression                            // har类型
|---view
|   |---ChatWithExpression.ets               // 视图层-表情聊天界面
|---constants
|   |---ChatConstants.ets                    // 常量
|---model
|   |---Emoji.ets                            // 表情资源
|   |---Message.ets                          // 消息结构
|   |---BasicDataSource.ets                  // 数据类型文件

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为体系杂乱无章,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)路线、视频、文档用来跟着学习是非常有必要的。

如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员

鸿蒙 NEXT 全栈开发学习笔记 希望这一份鸿蒙学习文档能够给大家带来帮助~

这份鸿蒙(HarmonyOS NEXT)包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、(南向驱动、嵌入式等)鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。


 鸿蒙(HarmonyOS NEXT)最新学习路线

​​

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.视频教程+学习PDF文档

(鸿蒙语法ArkTS、TypeScript、ArkUI教程……)全球开发者的开源社区,开源代码

 纯血版鸿蒙全套学习文档(面试、文档、全套视频等)全球开发者的开源社区,开源代码

                   

鸿蒙APP开发必备

​​​

总结

参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146946.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

混合开发-JSBridge

1.1 什么是混合开发? 混合开发是一种融合了原生开发和Web开发优势的移动应用开发方式。 具体来说,混合开发通常指的是利用一种框架或平台来创建应用程序,这种程序结合了原生应用的一些功能和特性(比如访问设备的摄像头、相册、GPS、蓝牙等…

DAMODEL——Llama3.1的部署与使用指南

Llama3.1的部署与使用指南 在自然语言处理(NLP)领域,大模型(LLM)是基于深度学习算法训练而成的重要工具,应用范围包括自然语言理解和生成。随着技术的发展,开源的LLM不断涌现,涵盖了…

Windows上通过VirtualBox安装Linux虚拟机

目录 一、安装VirtualBox 1. 下载VirtualBox 2. 安装VirtualBox 二、使用VirtualBox安装Linux系统 1. 下载Linux镜像 2. 使用VirtualBox新建虚拟环境 三、常见问题解决办法 1. Terminal打不开系统字符乱码 2. 窗口小和分辨率不匹配 一、安装VirtualBox 1. 下载Virtu…

10.2 溪降技术:双重检查

目录 10.2 双重检查概览观看视频课程电子书:双重检查场景场景 1场景 2 个人责任示例 1示例 2 总结 10.2 双重检查 概览 俗话说:“江山易改,本性难移”。在我们开始体验峡谷探险时,培养良好的习惯对我们的进一步发展至关重要。在所…

重生之我们在ES顶端相遇第15 章 - ES 的心脏-倒排索引

文章目录 前言为什么叫倒排索引数据结构如何生成如何查询TF、IDF参考文档 前言 上一章,简单介绍了 ES 的节点类型。 本章,我们要介绍 ES 中非常重要的一个概念:倒排索引。 ES 的全文索引就是基于倒排索引实现的。 本章内容建议重点学习&…

实现人体模型可点击

简化需求:实现项目内嵌人体模型,实现点击不同部位弹出部位名称 一:优先3d, 方案:基于three.js,.gltf格式模型,vue3 缺点:合适且免费的3d模型找不到,因为项目对部位有要…

Python实现贝叶斯优化器(Bayes_opt)优化卷积神经网络-双向长短时记忆循环神经网络回归模型(CNN-BiLSTM回归算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 随着大数据和计算能力的提升,深度学习模型在众多领域取得了显著的成功。然而,这…

Nature Communications|一种快速响应的智能可穿戴嗅觉接口(可穿戴电子/柔性电子/人机交互)

香港城市大学于欣格( Xinge Yu)、北京航空航天大学李宇航(Yuhang Li)、中国特种设备检验研究所赵召(Zhao Zhao)和东京大学Takao Someya团队,在《Nature Communications》上发布了一篇题为“Intelligent wearable olfactory interface for latency-free mixed reality and …

HAL库-4.3寸电容式接触屏LCD驱动(未完成)

目录 1.LCD介绍: 工作原理 显示特性 优缺点 2.LCD与OLED的区别: 1. 工作原理 2. 显示效果 3. 屏幕厚度与重量 4. 能耗 5. 寿命与稳定性 6. 应用场景 实验所用模块:ATK-4.3’ TFTLCD 原理图模块与数据手册介绍: LCD驱…

OpenAI GPT o1技术报告阅读(5)-安全性对齐以及思维链等的综合评估与思考

✨继续阅读报告:使用大模型来学习推理(Reason) 原文链接:https://openai.com/index/learning-to-reason-with-llms/ 编码 我们训练了一个模型,在2024年国际信息学奥林匹克竞赛(IOI)中得分213分,排名在第…

大数据实验一: Linux系统安装和使用

一、实验目的 描述Ubuntu的安装过程;使用命令完成Ubuntu中的基础操作; 二、实验平台 操作系统:window系统;内存:4G以上;硬盘:100GB以上;Virtual Box或者VMware;Ubuntu…

当大语言模型应用到教育领域时会有什么火花出现?

当大语言模型应用到教育领域时会有什么火花出现? LLM Education会出现哪些机遇与挑战? 今天笔者分享一篇来自New York University大学的研究论文,另外一篇则是来自Michigan State University与浙江师范大学的研究论文,希望对这个话题感兴趣…

Java反序列化利用链篇 | CC6链分析(通用版CC链)

文章目录 CC6和CC1之间的区别CC6的调用链构造CC6的payload完成TiedMapEntry.getValue()完成TiedMapEntry.hashCode()完成HashMap.hash()及HashMap.readObject()解决hash()方法提前触发的问题 系列篇其他文章,推荐顺序观看~ Java反序列化利用链篇 | JdbcRowSetImpl利…

FastAPI 的隐藏宝石:自动生成 TypeScript 客户端

在现代 Web 开发中,前后端分离已成为标准做法。这种架构允许前端和后端独立开发和扩展,但同时也带来了如何高效交互的问题。FastAPI,作为一个新兴的 Python Web 框架,提供了一个优雅的解决方案:自动生成客户端代码。本…

C语言-文件操作-一些我想到的、见到的奇怪的问题

博客主页:【夜泉_ly】 本文专栏:【C语言】 欢迎点赞👍收藏⭐关注❤️ C语言-文件操作-一些我想到的、见到的奇怪的问题 前言1.在不关闭文件的情况下,连续多次调用 fopen() 打开同一个文件,会发生什么?1.1过…

简单多状态dp第三弹 leetcode -买卖股票的最佳时机问题

309. 买卖股票的最佳时机含冷冻期 买卖股票的最佳时机含冷冻期 分析: 使用动态规划解决 状态表示: 由于有「买入」「可交易」「冷冻期」三个状态,因此我们可以选择用三个数组,其中: ▪ dp[i][0] 表示:第 i 天结束后&#xff0c…

基于主从Reactor模型实现高并发服务器

目录 1. 项目简介1.1 环境介绍1.2 项目定位1.3 功能模块整体划分 2. Reactor简介2.1 Reactor模型分析2.2 多Reactor多线程分析:多I/O多路复用线程池(业务处理) 3. 日志宏的编写4. Server模块4.1 Buffer模块4.1.1 Buffer的功能4.1.2 Buffer的实…

AI健身之俯卧撑计数和姿态矫正-角度估计

在本项目中,实现了Yolov7-Pose用于人体姿态估计。以下是如何在Windows 11操作系统上设置和运行该项目的详细步骤。 环境准备 首先,确保您的计算机已经安装了Anaconda。Anaconda是一个开源的Python发行版本,它包含了conda、Python以及众多科…

Python基于TensorFlow实现时间序列循环神经网络回归模型(LSTM时间序列回归算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 随着信息技术的发展和传感器设备的广泛应用,时间序列数据的产生量急剧增加。无论是股市价格…

Windows本地连接远程服务器并创建新用户详细记录

前提可知: (1)服务器IP地址:x.x.x.x (2)服务器名称:root(一般默认为root,当然也有别的名称) (3)服务器登陆密码:**** 一、…