鸿蒙NEXT开发案例:字数统计

【引言】
本文将通过一个具体的案例——“字数统计”组件,来探讨如何在鸿蒙NEXT框架下实现这一功能。此组件不仅能够统计用户输入文本中的汉字、中文标点、数字、以及英文字符的数量,还具有良好的用户界面设计,使用户能够直观地了解输入文本的各种统计数据。
【环境准备】
• 操作系统:Windows 10
• 开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806
• 目标设备:华为Mate60 Pro
• 开发语言:ArkTS
• 框架:ArkUI
• API版本:API 12
【组件概述】
“字数统计”组件基于鸿蒙NEXT框架构建,旨在提供一个简洁而强大的文本统计工具。组件的主要功能包括:
• 文本输入:用户可以在提供的文本区域内输入或粘贴任何文本。
• 实时统计:当用户输入或修改文本时,组件会实时更新并显示文本中汉字、中文标点、数字、英文字符等的具体数量。
• 示例与清空:提供了“示例”按钮,点击后会自动填充预设的文本内容;“清空”按钮则用于清空当前的输入内容。
【技术实现】
1. 状态管理:使用@State装饰器来管理组件的状态,如输入文本、各种字符的数量统计等。通过@Watch装饰器监听输入文本的变化,触发相应的计算逻辑。
2. 文本解析:当检测到输入文本发生变化时,组件会遍历文本中的每一个字符,根据正则表达式判断字符类型,并分别统计汉字、中文标点、数字、英文字符的数量。特别地,对于汉字和中文标点,每个字符被视为两个单位进行统计。
3. 用户界面:组件的UI设计遵循了鸿蒙NEXT的设计规范,使用了Column、Row、Text、TextArea等基础组件来构建布局。通过设置字体颜色、大小、背景色、边距等属性,实现了美观且易于使用的界面。此外,组件还利用了阴影效果和圆角设计来提升视觉体验。
4. 交互设计:为了增强用户体验,组件中加入了“示例”和“清空”按钮,用户可以通过简单的点击操作快速测试组件的功能或清空输入框。同时,组件支持文本输入区域的实时更新,保证了用户操作的即时反馈。
【完整代码】
// 定义一个组件,用于数字和文本统计
@Entry
@Component
struct NumberToChineseConverter {// 定义一个状态变量,存储示例数字字符串@State private exampleNumber: string = '自从盘古破鸿蒙,开辟从兹清浊辨。\nare you ok?\n1234\n+-*/';// 定义文本颜色的状态变量@State private textColor: string = "#2e2e2e";// 定义阴影边框颜色的状态变量@State private shadowColor: string = "#d5d5d5";// 定义基础内边距的状态变量@State private basePadding: number = 30;// 定义汉字数量的状态变量@State private chineseCharCount: string = "0";// 定义中文标点数量的状态变量@State private chinesePunctuationCount: string = "0";// 定义汉字加中文标点总数的状态变量@State private totalChineseCount: string = "0";// 定义英文字符数量的状态变量@State private englishCharCount: string = "0";// 定义数字数量的状态变量@State private digitCount: string = "0";// 定义总字符数的状态变量@State private charTotalCount: string = "0";// 定义监听输入文本变化的状态变量@State @Watch('inputChanged') private inputText: string = "";// 当输入文本发生变化时调用的方法inputChanged() {// 初始化计数器let chineseChars = 0; // 汉字数量let chinesePunctuation = 0; // 中文标点数量let englishChars = 0; // 英文字符数量let digits = 0; // 数字数量let count = 0; // 总字符数// 遍历输入文本的每个字符for (let i = 0; i < this.inputText.length; i++) {let char = this.inputText.charAt(i); // 获取当前字符count++; // 计数器加一// 如果字符是数字,则数字计数器加一if (/\d/.test(char)) {digits++;}// 如果字符是汉字,则汉字计数器加一,同时总字符数加二if (/[\u4e00-\u9fa5]/.test(char)) {chineseChars++;count++; // 汉字和中文标点算两个字符,所以这里多+1}// 如果字符是中文标点,则中文标点计数器加一,同时总字符数加二if (/[\u3001-\u3002\uff01-\uff1a]/.test(char)) {chinesePunctuation++;count++; // 汉字和中文标点算两个字符,所以这里多+1}// 如果字符是英文字符或英文标点,则英文字符计数器加一if (/[a-zA-Z0-9\s!-/:-@[-`{-~]/.test(char)) {englishChars++;}}// 更新状态变量this.chineseCharCount = `${chineseChars}`;this.chinesePunctuationCount = `${chinesePunctuation}`;this.totalChineseCount = `${chineseChars + chinesePunctuation}`;this.englishCharCount = `${englishChars}`;this.digitCount = `${digits}`;this.charTotalCount = `${count}`;}// 构建UI界面的方法build() {// 创建一个列布局容器Column() {// 添加标题Text('字数统计').fontColor(this.textColor) // 设置字体颜色.fontSize(18) // 设置字体大小.width('100%') // 设置宽度为100%.height(50) // 设置高度为50.textAlign(TextAlign.Center) // 设置文本居中对齐.backgroundColor(Color.White) // 设置背景色为白色.shadow({ // 设置阴影效果radius: 2, // 阴影半径color: this.shadowColor, // 阴影颜色offsetX: 0, // X轴偏移量offsetY: 5 // Y轴偏移量});// 创建可滚动的容器Scroll() {// 在可滚动容器内部创建列布局Column() {// 添加工具介绍Column() {Text('工具介绍').fontSize(18).fontWeight(600).fontColor(this.textColor);Text('本工具能够快速统计输入文本中的汉字、中文标点、数字、英文字符等的数量。具体规则如下:\n•汉字和中文标点各算作两个字符。\n•数字、空格、英文字母及英文标点各算作一个字符。').textAlign(TextAlign.JUSTIFY) // 设置文本两端对齐.fontSize(13) // 设置字体大小.fontColor(this.textColor) // 设置字体颜色.margin({ top: `${this.basePadding / 2}lpx` }); // 设置上边距}// 设置样式.alignItems(HorizontalAlign.Start) // 设置水平对齐方式.width('650lpx') // 设置宽度.padding(`${this.basePadding}lpx`) // 设置内边距.margin({ top: `${this.basePadding}lpx` }) // 设置外边距.borderRadius(10) // 设置圆角.backgroundColor(Color.White) // 设置背景色.shadow({ // 设置阴影效果radius: 10, // 阴影半径color: this.shadowColor, // 阴影颜色offsetX: 0, // X轴偏移量offsetY: 0 // Y轴偏移量});// 添加示例和清空按钮Column() {Row() {Text('示例').fontColor("#5871ce") // 设置字体颜色.fontSize(16) // 设置字体大小.padding(`${this.basePadding / 2}lpx`) // 设置内边距.backgroundColor("#f2f1fd") // 设置背景色.borderRadius(5) // 设置圆角.clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }) // 设置点击效果.onClick(() => { // 设置点击事件this.inputText = this.exampleNumber; // 将示例文本赋值给输入框});Blank(); // 添加空白间隔Text('清空').fontColor("#e48742") // 设置字体颜色.fontSize(16) // 设置字体大小.padding(`${this.basePadding / 2}lpx`) // 设置内边距.clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }) // 设置点击效果.backgroundColor("#ffefe6") // 设置背景色.borderRadius(5) // 设置圆角.onClick(() => { // 设置点击事件this.inputText = ""; // 清空输入框});}.height(45) // 设置高度.justifyContent(FlexAlign.SpaceBetween) // 设置子项之间间距均匀分布.width('100%'); // 设置宽度Divider(); // 添加分割线// 添加文本输入区域TextArea({ text: $$this.inputText, placeholder: `请输入内容` }).width(`${650 - this.basePadding * 2}lpx`) // 设置宽度.height(100) // 设置高度.fontSize(16) // 设置字体大小.caretColor(this.textColor) // 设置光标颜色.fontColor(this.textColor) // 设置字体颜色.margin({ top: `${this.basePadding}lpx` }) // 设置上边距.padding(0) // 设置内边距.backgroundColor(Color.Transparent) // 设置背景色.borderRadius(0) // 设置圆角.textAlign(TextAlign.JUSTIFY); // 设置文本两端对齐}// 设置样式.alignItems(HorizontalAlign.Start) // 设置水平对齐方式.width('650lpx') // 设置宽度.padding(`${this.basePadding}lpx`) // 设置内边距.margin({ top: `${this.basePadding}lpx` }) // 设置外边距.borderRadius(10) // 设置圆角.backgroundColor(Color.White) // 设置背景色.shadow({ // 设置阴影效果radius: 10, // 阴影半径color: this.shadowColor, // 阴影颜色offsetX: 0, // X轴偏移量offsetY: 0 // Y轴偏移量});// 添加统计结果展示Column() {// 汉字数量Row() {Text() {Span(`汉字:`)Span(`${this.chineseCharCount} `).fontColor(Color.Red) // 汉字数量以红色显示Span('个')}.fontColor(this.textColor) // 设置字体颜色.fontSize(16) // 设置字体大小.layoutWeight(1); // 设置布局权重}.constraintSize({ minHeight: 45 }) // 设置最小高度.justifyContent(FlexAlign.SpaceBetween) // 设置子项之间间距均匀分布.width('100%'); // 设置宽度Divider(); // 添加分割线// 中文标点数量Row() {Text() {Span(`中文标点:`)Span(`${this.chinesePunctuationCount} `).fontColor(Color.Red) // 中文标点数量以红色显示Span('个')}.fontColor(this.textColor) // 设置字体颜色.fontSize(16) // 设置字体大小.layoutWeight(1); // 设置布局权重}.constraintSize({ minHeight: 45 }) // 设置最小高度.justifyContent(FlexAlign.SpaceBetween) // 设置子项之间间距均匀分布.width('100%'); // 设置宽度Divider(); // 添加分割线// 汉字加中文标点总数Row() {Text() {Span(`汉字+中文标点:`)Span(`${this.totalChineseCount} `).fontColor(Color.Red) // 汉字加中文标点总数以红色显示Span('个')}.fontColor(this.textColor) // 设置字体颜色.fontSize(16) // 设置字体大小.layoutWeight(1); // 设置布局权重}.constraintSize({ minHeight: 45 }) // 设置最小高度.justifyContent(FlexAlign.SpaceBetween) // 设置子项之间间距均匀分布.width('100%'); // 设置宽度Divider(); // 添加分割线// 英文字符数量Row() {Text() {Span(`英文:`)Span(`${this.englishCharCount} `).fontColor(Color.Red) // 英文字符数量以红色显示Span('个')Span('(含英文状态下的数字、符号、标点)').fontSize(13) // 附加说明}.fontColor(this.textColor) // 设置字体颜色.fontSize(16) // 设置字体大小.layoutWeight(1); // 设置布局权重}.constraintSize({ minHeight: 45 }) // 设置最小高度.justifyContent(FlexAlign.SpaceBetween) // 设置子项之间间距均匀分布.width('100%'); // 设置宽度Divider(); // 添加分割线// 数字数量Row() {Text() {Span(`数字:`)Span(`${this.digitCount} `).fontColor(Color.Red) // 数字数量以红色显示Span('个')}.fontColor(this.textColor) // 设置字体颜色.fontSize(16) // 设置字体大小.layoutWeight(1); // 设置布局权重}.constraintSize({ minHeight: 45 }) // 设置最小高度.justifyContent(FlexAlign.SpaceBetween) // 设置子项之间间距均匀分布.width('100%'); // 设置宽度Divider(); // 添加分割线// 总字符数Row() {Text() {Span(`字符总数:`)Span(`${this.charTotalCount} `).fontColor(Color.Red) // 总字符数以红色显示Span('个字符')}.fontColor(this.textColor) // 设置字体颜色.fontSize(16) // 设置字体大小.layoutWeight(1); // 设置布局权重}.constraintSize({ minHeight: 45 }) // 设置最小高度.justifyContent(FlexAlign.SpaceBetween) // 设置子项之间间距均匀分布.width('100%'); // 设置宽度}// 设置样式.alignItems(HorizontalAlign.Start) // 设置水平对齐方式.width('650lpx') // 设置宽度.padding(`${this.basePadding}lpx`) // 设置内边距.margin({ top: `${this.basePadding}lpx` }) // 设置外边距.borderRadius(10) // 设置圆角.backgroundColor(Color.White) // 设置背景色.shadow({ // 设置阴影效果radius: 10, // 阴影半径color: this.shadowColor, // 阴影颜色offsetX: 0, // X轴偏移量offsetY: 0 // Y轴偏移量});}}.scrollBar(BarState.Off) // 关闭滚动条.clip(false); // 不裁剪超出部分,这里是允许内部组件阴影可以向父布局外扩散}.height('100%') // 设置高度为100%.width('100%') // 设置宽度为100%.backgroundColor("#f4f8fb"); // 设置背景色}
}
相关文章:
鸿蒙NEXT开发案例:字数统计
【引言】 本文将通过一个具体的案例——“字数统计”组件,来探讨如何在鸿蒙NEXT框架下实现这一功能。此组件不仅能够统计用户输入文本中的汉字、中文标点、数字、以及英文字符的数量,还具有良好的用户界面设计,使用户能够直观地了解输入文本…...
uniapp vue2项目迁移vue3项目
uniapp vue2项目迁移vue3项目,必须适配的部分 一、main.js 创建应用实例 // 之前 - Vue 2 import Vue from vue import App from ./App Vue.config.productionTip false // vue3 不再需要 App.mpType app // vue3 不再需要 const app new Vue({ ...App }) …...
16.C++STL 3(string类的模拟,深浅拷贝问题)
⭐本篇重点:string类的模拟,自己实现一个简单的string类 ⭐本篇代码:c学习/05.string类的学习 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 经典string类的模拟 1.1 深浅拷贝问题 1.2 使用深拷贝完成经典string类的…...
神经网络10-Temporal Fusion Transformer (TFT)
Temporal Fusion Transformer (TFT) 是一种专为时序数据建模而设计的深度学习模型,它结合了Transformer架构和其他技术,旨在有效地处理和预测时序数据中的复杂模式。TFT 于 2020 年由 Google Research 提出,旨在解决传统模型在时序预测中的一…...
“iOS profile文件与私钥证书文件不匹配”总结打ipa包出现的问题
目录 文件和证书未加载或特殊字符问题 证书过期或Profile文件错误 确认开发者证书和私钥是否匹配 创建证书选择错误问题 申请苹果 AppId时勾选服务不全问题 总结 在上线ios平台的时候,在Hbuilder中打包遇见了问题,生成ipa文件时候,一…...
《图像梯度与常见算子全解析:原理、用法及效果展示》
简介:本文深入探讨图像梯度相关知识,详细介绍图像梯度是像素灰度值在不同方向的变化速度,并以 “pig.JPG” 图像为例,通过代码展示如何选取图像部分区域并分析其像素值以论证图像梯度与边缘信息的关联。接着全面阐述了 Sobel 算子,…...
【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓
✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨文章所属专栏:c篇–CSDN博客 文章目录 前言一.std::string对象的创建二.std::string对象的访问三.std::str…...
LlamaIndex ollama 搭建本地RAG应用,建立本地知识库
目录 简介安装前的准备下载ollama创建llamaindex conda环境,为后面编码作准备 环境变量迁移ollama到其他盘运行ollama方式一方式二禁止ollama开机自启动运行第一个模型 Chatbox聊天下载Chatbox配置ollama地址和模型验证 建立自身特定知识数据搭配大语言模型创建项目…...
draggable的el-dialog实现对话框标题可以选择
请看图 这个对话框使用了el-dialog并且draggable属性设置成了true,所以标题栏这里就可以拖动,现在用户想选中标题栏的文本进而复制。我看到这个需求头都大了。 我能想到的方案有三个:1. 取消draggable为true 2. 标题文案后面加一个复制按钮 …...
2024年Android面试总结
2024年Android面试总结 1.动画类型有哪些?插值器原理? 2.StringBuffer和StringBuilder区别? 3.jvm内存模型? 4.线程池7大核心参数及原理? 5.Android多进程通信方式有哪些?各自的优缺点? 6…...
树莓派3:64位系统串口(UART)使用问题的解决方法
前言 当我们要使用串口进行zigbee的短距离通信时,发现无法使用串口. 原因 树莓派3bCPU内部有两个串口,一个硬件串口(就是我们平时使用的UART),还有一个迷你串口(mini-uart),在老版本的树莓派中把硬件串口分配在GPIO上,可以单独使用.但是在新的树莓派中官方把硬件串口给了蓝牙…...
SemiDrive E3 硬件设计系列---唤醒电路设计
一、前言 E3 系列芯片是芯驰半导体高功能安全的车规级 MCU,对于 MCU 的硬件设计部分,本系列将会分模块进行讲解,旨在介绍 E3 系列芯片在硬件设计方面的注意事项与经验,本文主要讲解 E3 硬件设计中唤醒电路部分的设计。 二、RTC 模…...
淘宝接口高并发采集核心要点解读,开启电商数据智能应用新纪元
一、引言 在电商蓬勃发展的今天,淘宝作为全球知名的电商巨头,其平台上的数据犹如一座蕴藏无限价值的宝藏。准确且高效地采集淘宝接口数据,并通过高并发技术实现大规模数据获取,对于电商企业的精准营销、市场趋势分析、竞品监测以及…...
C#里怎么样快速使用LINQ实现查询?
C#里怎么样快速使用LINQ实现查询? 在C#里使用LINQ,是一个方便的功能, 不过,要学会使用这部分的功能,需要比较多的学习时间,否则,使用起就比较难。 因为它的表现方式,与编程语言通用的功能,还是差别比较大。 当数据量比较小,没有特定的顺序时,使用LINQ访问会比较好…...
2024新版微软edge浏览器输入百度网址时自动补全tn=68018901……小尾巴的解决
以前一直是Windows11 21h2版本,浏览器内输入baidu不会自动补全tnxx的百度推广小尾巴。然后前几天在BIOS内开启了tpm2.0,升级Windows11到了24h2版本。 发现在edge浏览器内只要输入b,就会自动补全为baidu.com?tnXXX的这么一个百度推广形式。开…...
uni-app打包H5自定义微信分享
1、配置分享信息 修改uni-app的index.html,添加Open Graph(OG)标签来配置分享信息。 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="description" content="标题"/>…...
大模型专栏--大模型应用场景
紧接着第一篇,什么是大模型,这篇文章讨论一下大模型的应用场景和应用方式有哪些? 基础使用 随着 GPT 的出现,AI 大模型已经越来越多得出现在日常生活和学术研究,工作中。 按照使用方向有以下几种: 自然语…...
骑砍2霸主MOD开发(29)-顶点动画
一.定制化顶点动画(MorphAnimation) 定制化顶点动画用于人物Agent的面部表情. 1.创建MorphAnimation对应静态资源morph_animation.tpac 2.Agent设置对应MorphAnimation [EngineMethod("set_agent_facial_animation", false)] void SetAgentFacialAnimation(UIntPtr …...
-Dspring.profiles.active=dev与--spring.profiles.active=dev的区别
在Spring Boot应用程序中,-Dspring.profiles.activedev和--spring.profiles.activedev都用于指定要激活的Spring配置文件(profile),但它们在不同的环境中使用,并且有不同的作用域。 -Dspring.profiles.activedev&#…...
面向对象高级(2)单例设计对象与代码块
面向对象高级(2) 单例设计模式、main方法与代码块 引言; 设计模式:特定环境下特定问题的处理方法。可理解为一种经典的可以参照的模板。单例设计模式则是只存在单个对象实例、且只有一种方法获取对象实例的一种设计模式。 单例设…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
