鸿蒙NEXT开发案例:颜文字搜索器

【引言】

本文将介绍一个名为“颜文字搜索器”的开发案例,该应用是基于鸿蒙NEXT平台构建的,旨在帮助用户快速查找和使用各种风格的表情符号。通过本案例的学习,读者可以了解如何在鸿蒙平台上进行数据处理、UI设计以及交互逻辑的实现。

【环境准备】

• 操作系统:Windows 10

• 开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806

• 目标设备:华为Mate60 Pro

• 开发语言:ArkTS

• 框架:ArkUI

• API版本:API 12

【开发思路】

1. 数据模型设计

为了表示单个表情符号的信息,我们定义了一个 EmoticonBean 类,它包含了表情符号的风格(style)、类型(type)、表情符号本身(emoticon)及其含义(meaning)。此外,还添加了一个布尔属性 isShown 来追踪表情符号是否应该显示给用户,这有助于在搜索时动态更新列表。

2. UI 组件与布局

应用的主界面由一个 Index 组件构成,它负责整体布局的设计。界面上部是一个搜索框,允许用户输入关键词来过滤表情符号列表。下方则以表格形式展示了所有符合条件的表情符号,每一行包括四个部分:风格、类型、表情符号和含义。为了提升用户体验,当用户点击某个表情符号或其含义中的高亮文本时,会触发相应的点击事件,并输出日志信息。

3. 数据加载与处理

表情符号的数据来源于一个本地 JSON 文件 (emoticons.json),该文件在组件初次渲染之前被读取并解析为 EmoticonBean 对象数组。每次用户修改搜索框中的内容时,都会调用 splitAndHighlight 方法对每个表情符号的含义进行分割,并检查是否存在匹配的关键字。如果存在,则设置 isShown 属性为 true,否则为 false,以此控制表情符号是否在界面上显示。

4. 搜索与高亮

splitAndHighlight 函数用于将表情符号的含义按关键字分割成多个片段,并返回这些片段组成的数组。对于包含关键字的片段,会在界面上以不同的颜色高亮显示,从而直观地指出匹配的部分。此外,此函数还会根据是否有匹配项来决定表情符号是否可见,确保只有相关的表情符号才会展示给用户。

5. 用户交互

为了让用户有更好的操作体验,我们在界面上实现了触摸事件监听,当用户点击非输入区域时,自动关闭键盘。这样既保证了界面整洁,又简化了用户的操作流程。

【完整代码】

数据源:src/main/resources/rawfile/emoticons.json

https://download.csdn.net/download/zhongcongxu01/90126325

代码

// 引入必要的工具库 util 用于文本解码等操作
import { util } from '@kit.ArkTS'
// 引入 BusinessError 类用于处理业务逻辑错误
import { BusinessError } from '@kit.BasicServicesKit'
// 引入 inputMethod 模块用于管理输入法行为
import { inputMethod } from '@kit.IMEKit'// 定义一个可以被观察的数据模型 EmoticonBean 表示单个表情符号的信息
@ObservedV2
class EmoticonBean {// 定义风格属性,并初始化为空字符串style: string = ""// 定义类型属性,并初始化为空字符串type: string = ""// 定义表情符号本身,并初始化为空字符串emoticon: string = ""// 定义含义属性,并初始化为空字符串meaning: string = ""// 构造函数,允许在创建对象时设置上述属性constructor(style: string, type: string, emoticon: string, meaning: string) {this.style = stylethis.type = typethis.emoticon = emoticonthis.meaning = meaning}// 定义是否显示的表情符号状态标记,默认为 true,使用 @Trace 装饰器使其可追踪变化@Trace isShown: boolean = true
}// 使用 @Entry 和 @Component 装饰器定义 Index 组件作为应用入口
@Entry
@Component
struct Index {// 定义一个状态变量 textInput 用于存储搜索框中的文本内容,默认为空字符串@State private textInput: string = ''// 定义一个状态变量 emoticonList 用于存储表情符号列表,默认为空数组@State private emoticonList: EmoticonBean[] = []// 定义线条颜色属性private lineColor: string = "#e6e6e6"// 定义标题背景色属性private titleBackground: string = "#f8f8f8"// 定义文本颜色属性private textColor: string = "#333333"// 定义基础填充大小private basePadding: number = 4// 定义线条宽度private lineWidth: number = 2// 定义单元格高度private cellHeight: number = 50// 定义列权重比例private weightRatio: number[] = [1, 1, 5, 4]// 定义基础字体大小private baseFontSize: number = 14// 定义一个方法 splitAndHighlight 用于分割并高亮表情符号含义中的关键词private splitAndHighlight(item: EmoticonBean, keyword: string): string[] {let text = item.meaning // 获取表情符号的含义文本if (!keyword) { // 如果没有关键词,则直接返回整个文本,并显示该表情符号item.isShown = truereturn [text]}let segments: string[] = []; // 用于存储分割后的文本片段let lastMatchEnd: number = 0; // 记录上一次匹配结束的位置while (true) { // 循环查找关键词在文本中的位置const matchIndex = text.indexOf(keyword, lastMatchEnd); // 查找关键词出现的位置if (matchIndex === -1) { // 如果找不到关键词,将剩余文本加入到segments中并退出循环segments.push(text.slice(lastMatchEnd));break;} else { // 如果找到关键词,将非关键词部分和关键词部分分别加入到segments中segments.push(text.slice(lastMatchEnd, matchIndex)); // 非关键词部分segments.push(text.slice(matchIndex, matchIndex + keyword.length)); // 关键词部分lastMatchEnd = matchIndex + keyword.length;}}// 如果有关键词出现,则设置表情符号为显示状态item.isShown = (segments.indexOf(keyword) != -1)return segments;}// 当组件即将出现在屏幕上时调用此方法,用于加载表情符号数据aboutToAppear() {// 从资源管理器中读取本地文件 emoticons.json 的内容getContext().resourceManager.getRawFileContent("emoticons.json", (err: BusinessError, data) => {if (err) { // 如果读取失败,打印错误信息console.error('getRawFileContent error: ' + JSON.stringify(err))return}// 创建一个文本解码器来将二进制数据转换为字符串let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true })let jsonString = textDecoder.decodeToString(data, { stream: false })let jsonObjectArray: object[] = JSON.parse(jsonString) // 将 JSON 字符串解析为对象数组for (let i = 0; i < jsonObjectArray.length; i++) { // 遍历对象数组,填充 emoticonListlet item = jsonObjectArray[i]this.emoticonList.push(new EmoticonBean(item['s'], item['t'], item['e'], item['m']))}try {// 打印 emoticonList 到控制台以供调试console.info(`this.emoticonList:${JSON.stringify(this.emoticonList, null, '\u00a0\u00a0')}`)} catch (err) {console.error('parse error: ' + JSON.stringify(err))}})}// 定义 build 方法构建组件的UI结构build() {Column({ space: 0 }) { // 创建一个列容器,内部元素之间没有间距// 搜索框组件,绑定到 textInput 状态变量Search({ value: $$this.textInput }).margin(this.basePadding) // 设置外边距.fontFeature("\"ss01\" on") // 设置字体特征// 创建一个列容器用于表头Column() {Row() { // 创建一行用于放置表头// 表头文字:风格Text('风格').height('100%') // 设置高度为父容器的100%.layoutWeight(this.weightRatio[0]) // 根据权重分配宽度.textAlign(TextAlign.Center) // 文本居中对齐.fontSize(this.baseFontSize) // 设置字体大小.fontWeight(600) // 设置字体粗细.fontColor(this.textColor) // 设置文本颜色// 分割线Line().height('100%').width(this.lineWidth).backgroundColor(this.lineColor)// 表头文字:类型Text('类型').height('100%').layoutWeight(this.weightRatio[1]).textAlign(TextAlign.Center).fontSize(this.baseFontSize).fontWeight(600).fontColor(this.textColor)// 分割线Line().height('100%').width(this.lineWidth).backgroundColor(this.lineColor)// 表头文字:表情Text('表情').height('100%').layoutWeight(this.weightRatio[2]).textAlign(TextAlign.Center).fontSize(this.baseFontSize).fontWeight(600).fontColor(this.textColor)// 分割线Line().height('100%').width(this.lineWidth).backgroundColor(this.lineColor)// 表头文字:含义Text('含义').height('100%').layoutWeight(this.weightRatio[3]).textAlign(TextAlign.Center).fontSize(this.baseFontSize).fontWeight(600).fontColor(this.textColor)}.height(this.cellHeight).borderWidth(this.lineWidth).borderColor(this.lineColor).backgroundColor(this.titleBackground) // 设置背景颜色}.width(`100%`).padding({ left: this.basePadding, right: this.basePadding })// 创建一个滚动容器 Scroll 包含表情符号列表Scroll() {Column() {// ForEach 循环遍历 emoticonList 数组,创建每一行代表一个表情符号条目ForEach(this.emoticonList, (item: EmoticonBean) => {Row() {// 显示表情符号的风格Text(item.style).height('100%').layoutWeight(this.weightRatio[0]).textAlign(TextAlign.Center).fontSize(this.baseFontSize).fontColor(this.textColor)// 分割线Line().height('100%').width(this.lineWidth).backgroundColor(this.lineColor)// 显示表情符号的类型Text(item.type).height('100%').layoutWeight(this.weightRatio[1]).textAlign(TextAlign.Center).fontSize(this.baseFontSize).fontColor(this.textColor)// 分割线Line().height('100%').width(this.lineWidth).backgroundColor(this.lineColor)// 显示表情符号Text(item.emoticon).height('100%').layoutWeight(this.weightRatio[2]).textAlign(TextAlign.Center).fontSize(this.baseFontSize).fontColor(this.textColor).copyOption(CopyOptions.LocalDevice) // 允许复制到剪贴板// 分割线Line().height('100%').width(this.lineWidth).backgroundColor(this.lineColor)// 显示表情符号的含义,支持关键字高亮Text() {ForEach(this.splitAndHighlight(item, this.textInput), (segment: string, index: number) => {ContainerSpan() {Span(segment).fontColor(segment === this.textInput ? Color.White : Color.Black) // 根据是否是关键词设置字体颜色.onClick(() => { // 设置点击事件监听器console.info(`Highlighted text clicked: ${segment}`); // 打印点击的文本信息console.info(`Click index: ${index}`); // 打印点击的索引信息});}.textBackgroundStyle({color: segment === this.textInput ? Color.Red : Color.Transparent // 根据是否是关键词设置背景颜色});});}.height('100%').layoutWeight(this.weightRatio[3]).textAlign(TextAlign.Center).fontSize(this.baseFontSize).fontColor(this.textColor).padding({ left: this.basePadding, right: this.basePadding })}.height(this.cellHeight).borderWidth({ left: this.lineWidth, right: this.lineWidth, bottom: this.lineWidth }).borderColor(this.lineColor)// 根据表情符号的状态(是否显示)来决定其可见性.visibility(item.isShown ? Visibility.Visible : Visibility.None)})}.width(`100%`).padding({ left: this.basePadding, right: this.basePadding })}.width('100%').layoutWeight(1).align(Alignment.Top)// 触摸事件处理,当用户点击空白区域时,关闭键盘输入.onTouch((event) => {if (event.type == TouchType.Down) { // 如果是按下事件inputMethod.getController().stopInputSession() // 停止当前的输入会话}})}.width('100%').height('100%').backgroundColor(Color.White); // 设置容器的宽高和背景颜色}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速部署一套K8s集群-v1.28

快速部署一套K8s集群-v1.28 1.前置知识点 1.1 生产环境可部署Kubernetes集群的两种方式 目前生产部署Kubernetes集群主要有两种方式: kubeadmKubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。 二进制包从github下载发行版的二进…

【硬件测试】基于FPGA的4ASK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.Verilog核心程序 4.开发板使用说明和如何移植不同的开发板 5.完整算法代码文件获得 1.算法仿真效果 本文是之前写的文章: 《基于FPGA的4ASK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR》 的…

用友U8+ API接口使用教程

前言 U8和其他的公开的开放API接口有一些差异&#xff0c;他是需要先对接的到代理服务器&#xff0c;通过代理服务器进行对接&#xff0c;所以只要保证U8能上网就能对接&#xff0c;和畅捷通T的模式有点类似 流程&#xff1a; 注册成为开发者&#xff08;用于创建用友U8 API应…

检查读取数据寄存器输出的多扇出

为使第二寄存器被 RAM 原语吸收&#xff0c;来自存储器阵列的数据输出位的扇出必须为 1 。这在下图中进行了说明。 检查地址 / 读取数据寄存器上的复位信号 不应复位存储器阵列。只有 RAM 的输出可以容许复位。复位必须是同步的&#xff0c;以便将输出寄存器推断到 RAM 基元…

MongoDB-ObjectID 生成器

前言 MongoDB中一个非常关键的概念就是 ObjectID&#xff0c;它是 MongoDB 中每个文档的默认唯一标识符。了解 ObjectID 的生成机制不仅有助于开发人员优化数据库性能&#xff0c;还能帮助更好地理解 MongoDB 的设计理念。 什么是 MongoDB ObjectID&#xff1f; 在 MongoDB …

渗透测试工具 -- SQLmap安装教程及使用

随着网络安全问题日益严峻&#xff0c;渗透测试成为了保护信息安全的重要手段。而在渗透测试的众多工具中&#xff0c;SQLmap凭借其强大的自动化SQL注入检测和利用能力&#xff0c;成为了网络安全专家必备的利器。那么&#xff0c;你知道如何高效地使用SQLmap进行漏洞扫描吗&am…

SpringBoot 整合 RabbitMQ 实现流量消峰

RabbitMQ 即一个消息队列&#xff0c;主要是用来实现应用程序的异步和解耦&#xff0c;同时也能起到消息缓冲&#xff0c;消息分发的作用。 消息中间件在互联网公司的使用中越来越多&#xff0c;刚才还看到新闻阿里将 RocketMQ 捐献给了 Apache&#xff0c;当然了今天的主角还…

Git-分支(branch)常用命令

分支 我们在做项目开发的时候&#xff0c;无论是软件项目还是其他机械工程项目&#xff0c;我们为了提高效率以及合理的节省时间等等原因&#xff0c;现在都不再是线性进行&#xff0c;而是将一个项目抽离出诸进行线&#xff0c;每一条线在git中我们就叫做分支&#xff0c;bran…

springboot425滑雪场管理系统(论文+源码)_kaic

摘要 近年来&#xff0c;信息化管理行业的不断兴起&#xff0c;使得人们的日常生活越来越离不开计算机和互联网技术。首先&#xff0c;根据收集到的用户需求分析&#xff0c;对设计系统有一个初步的认识与了解&#xff0c;确定滑雪场管理系统的总体功能模块。然后&#xff0c;详…

好玩的汇编编译器NASM:一款基于x86架构的汇编与反汇编软件

好玩的汇编编译器NASM This is the project webpage for the Netwide Assembler (NASM), an asssembler for the x86 CPU architecture portable to nearly every modern platform, and with code generation for many platforms old and new. Netwide Assembler&#xff08;…

【AI知识】有监督学习分类任务之支持向量机

1.支持向量机概念 支持向量机&#xff08;Support Vector Machine, SVM&#xff09; 是一种有监督学习算法&#xff0c;主要用于分类任务&#xff08;也可用于回归任务&#xff0c;即支持向量回归&#xff0c;SVR&#xff09;。SVM的核心思想是找到一个最优的超平面&#xff0…

杭州乘云联合信通院发布《云计算智能化可观测性能力成熟度模型》

原文地址&#xff1a;杭州乘云联合中国信通院等单位正式发布《云计算智能化可观测性能力成熟度模型》标准 2024年12月3日&#xff0c;由全球数字经济大会组委会主办、中国信通院承办的 2024全球数字经济大会 云AI计算创新发展大会&#xff08;2024 Cloud AI Compute Ignite&…

【经典】制造供应链四类策略(MTS、MTO、ATO、ETO)细说

关注作者 制造供应链的牛鞭问题与复杂问题主要是从两个方面解决&#xff0c;一是同步化供应链消减从需求到供应的放大效应&#xff0c;二是供应链细分&#xff0c;针对不同的客户、不同的需求供应的匹配策略来应对复杂性&#xff0c;更好的满足客户并以最低的总成本来实现。 对…

实时日志与发展:Elasticsearch 推出全新专用的 logsdb 索引模式

作者&#xff1a;来自 Elastic Mark Settle, George Kobar 及 Amena Siddiqi Elastic 最新发布的 logsdb 索引模式是专为日志管理优化的功能&#xff0c;旨在提升日志数据的存储效率、查询性能以及整体可用性。这个模式专注于满足现代日志处理需求&#xff0c;提供更高效的日志…

React Image Crop——在React应用中轻松实现图片裁剪功能

React Image Crop是一个用于在React应用程序中裁剪和调整图像的库。它提供了一个简单而强大的界面&#xff0c;允许用户选择和调整裁剪区域&#xff0c;并生成裁剪后的图像。 什么是React Image Crop&#xff1f; React Image Crop是一个开源的React组件&#xff0c;用于在浏览…

【HarmonyOS】鸿蒙应用实现手机摇一摇功能

【HarmonyOS】鸿蒙应用实现手机摇一摇功能 一、前言 手机摇一摇功能&#xff0c;是通过获取手机设备&#xff0c;加速度传感器接口&#xff0c;获取其中的数值&#xff0c;进行逻辑判断实现的功能。 在鸿蒙中手机设备传感器ohos.sensor (传感器)的系统API监听有以下&#xf…

微积分复习笔记 Calculus Volume 2 - 3.7 Improper Integrals

3.7 Improper Integrals - Calculus Volume 2 | OpenStax

ViewModel

ViewMode是MVVM架构模式中VM层对应的类&#xff0c;它的作用是存储界面数据&#xff0c;并和界面发生数据交互。ViewModel能感知生命周期&#xff0c;并且在界面由于配置问题发生重建时候&#xff0c;可以保持当前的数据不变。生命周期如下&#xff1a; ViewMode由ViewModePr…

智慧城市道路分割数据集labelme格式2648张1类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;2648 标注数量(json文件个数)&#xff1a;2648 标注类别数&#xff1a;1 标注类别名称:["road"] 每个类别标注的框数&#x…

leetcode-73.矩阵置零-day5

class Solution {public void setZeroes(int[][] mat) {int m mat.length, n mat[0].length;// 1. 扫描「首行」和「首列」记录「首行」和「首列」是否该被置零boolean r0 false, c0 false;for (int i 0; i < m; i) {if (mat[i][0] 0) {r0 true;break;}}for (int j …