HarmonyOS角落里的知识:一杯冰美式的时间 -- 之打字机

一、前言

模拟编辑器或者模拟输入框中文字啪啦啪啦输入的效果,往往能够吸引人们的眼球,让用户的注意力聚焦在输入的内容上,本文将和大家探讨打字机效果的实现方式以及应用。Demo基于API12。

二、思路

拆分开来很简单,将字符串拆分,只需把要展示的文本进行切割,使用定时器不断追加文字即可。光标我们可以使用自带的TextArea来实现。

效果如下:

三、数据源

随便抄了一段文本:

     private targetTxt: string = `碧海青天夜夜心,闲云潭影日悠悠。
 花开堪折直须折,莫待无花空折枝。
 江南好,风景旧曾谙。日出江花红胜火,春来江水绿如蓝。能不忆江南?
 ​
 松风吹解带,山月照弹琴。
 遥望洞庭山水翠,白银盘里一青螺。
 人生若只如初见,何事秋风悲画扇?
 ​
 浮生若梦,为欢几何?
 长风破浪会有时,直挂云帆济沧海。
 岁月不居,时节如流。人生天地间,若白驹过隙,忽然而已。
 ​
 愿逐月华流照君,千里共婵娟。 `

分割:

 aboutToAppear(): void {
     this.targetTxtArray = this.targetTxt.split("");
 }

准备一个@State变量,用于显示UI

 @State currentTxt: string = ""

四、TextArea

使用TextArea要面对的就是输入框是有焦点和事件以及配套的键盘的,同时又需要光标。如下:

 TextArea({
     text: this.currentTxt
 })
     .width("auto")
     .height("auto")
     .animation({ duration: 200, curve: Curve.Smooth })
     .focusable(true)
     .defaultFocus(true)
     .enableKeyboardOnFocus(false)
     .fontColor("#fefae0")
     .caretColor("#d4a373")
     .backgroundColor("#ccd5ae")
     .hitTestBehavior(HitTestMode.None)
  • 使用focusable(true)defaultFocus(true)来获取焦点,达到显示光标的效果。
  • enableKeyboardOnFocus(false) 用于限制它弹出键盘
  • hitTestBehavior(HitTestMode.None)则屏蔽了所有的事件

我们得到了一个干净的,有光标的,无法操作的输入框~

五、setInterval

显然需要一个定时器来间隔添加文字。

 @State currentProgress: number = 0
 @State inputStepChar: number = 1
 private inputTxt(step: number) {
     if (this.intervalId != -1) {
         clearInterval(this.intervalId)
         this.intervalId = -1
     }
     this.intervalId = setInterval(() => {
          if (this.currentProgress >= this.targetTxtArray.length - 1) {
              clearInterval(this.intervalId)
              break
          } else {
              this.currentTxt += this.targetTxtArray[++ this.currentProgress]
          }
     }, step)
 }

因为可能被多次调用,我们需要存一个定时器ID,在后续的触发中将定时器清除。

step就是输入的间隔了,也就是输入速度。

每间隔一次,就在数组中取一个字符串,直到取完。

六、删除

因为有输入,那就可以有删除,也很简单。反过来就行了~

  private removeTxt(step: number) {
      if (this.intervalId != -1) {
          clearInterval(this.intervalId)
          this.intervalId = -1
      }
      this.intervalId = setInterval(() => {
          if (this.currentProgress <= 0) {
              clearInterval(this.intervalId)
          } else {
              this.currentProgress--
              this.currentTxt = this.currentTxt.substring(0, this.currentTxt.length - 1);
          }
      }, step)
  }

每间隔一次,就在currentTxt中移除最后一个字符,并currentProgress递减,直到删完。

七、删除、添加多个

默认是一个个增加,一个个删除。多个的话,我们直接点。使用一个For循环,将原有的逻辑套进去就好了。

 private inputTxt(step: number) {
     if (this.intervalId != -1) {
         clearInterval(this.intervalId)
         this.intervalId = -1
     }
     this.intervalId = setInterval(() => {
         for (let index = 0; index < this.inputStepChar; index++) {
             if (this.currentProgress >= this.targetTxtArray.length - 1) {
                 clearInterval(this.intervalId)
                 break
             } else {
                 this.currentTxt += this.targetTxtArray[++ this.currentProgress]
             }
         }
     }, step)
 }

inputStepChar就是每次改变的字符数了,想多少就多少。

八、最终代码

 let maxSpeed: number = 1000
 let minSpeed: number = 50
 let minStepChar: number = 1
 let maxStepChar: number = 10
 ​
 ​
 /**
  * @Des
  * @Author zyc
  * @Date 2024/5/30
  */
 @Component
 export struct TypeWriterComponent {
     private targetTxt: string = `碧海青天夜夜心,闲云潭影日悠悠。
 花开堪折直须折,莫待无花空折枝。
 江南好,风景旧曾谙。日出江花红胜火,春来江水绿如蓝。能不忆江南?
 ​
 松风吹解带,山月照弹琴。
 遥望洞庭山水翠,白银盘里一青螺。
 人生若只如初见,何事秋风悲画扇?
 ​
 浮生若梦,为欢几何?
 长风破浪会有时,直挂云帆济沧海。
 岁月不居,时节如流。人生天地间,若白驹过隙,忽然而已。
 ​
 愿逐月华流照君,千里共婵娟。 `
     private intervalId: number = -1
     private targetTxtArray: string[] = []
     private defInputSpeed: number = 200
     private defRemoveSpeed: number = 100
     @State inputStepChar: number = 1
     @State removeStepChar: number = 1
     @State currentProgress: number = 0
     @State currentTxt: string = ""
     @State inputSpeed: number = 0
     @State removeSpeed: number = 0
 ​
     aboutToAppear(): void {
         this.targetTxtArray = this.targetTxt.split("");
         this.defRemoveSpeed = Math.abs(this.defRemoveSpeed - maxSpeed) + minSpeed
         this.defInputSpeed = Math.abs(this.defInputSpeed - maxSpeed) + minSpeed
         this.removeSpeed = this.defRemoveSpeed
         this.inputSpeed = this.defInputSpeed
     }
 ​
     private inputTxt(step: number) {
         if (this.intervalId != -1) {
             clearInterval(this.intervalId)
             this.intervalId = -1
         }
         this.intervalId = setInterval(() => {z
             for (let index = 0; index < this.inputStepChar; index++) {
                 if (this.currentProgress >= this.targetTxtArray.length - 1) {
                     clearInterval(this.intervalId)
                     break
                 } else {
                     this.currentTxt += this.targetTxtArray[++ this.currentProgress]
                 }
             }
         }, step)
     }
 ​
     private removeTxt(step: number) {
         if (this.intervalId != -1) {
             clearInterval(this.intervalId)
             this.intervalId = -1
         }
         this.intervalId = setInterval(() => {
             for (let index = 0; index < this.removeStepChar; index++) {
                 if (this.currentProgress <= 0) {
                     clearInterval(this.intervalId)
                     break
                 } else {
                     this.currentProgress--
                     this.currentTxt = this.currentTxt.substring(0, this.currentTxt.length - 1);
                 }
             }
 ​
         }, step)
     }
 ​
     build() {
         Column({ space: 10 }) {
             TextArea({
                 text: this.currentTxt
             })
                 .width("auto")
                 .height("auto")
                 .animation({ duration: 200, curve: Curve.Smooth })
                 .focusable(true)
                 .defaultFocus(true)
                 .enableKeyboardOnFocus(false)
                 .fontColor("#fefae0")
                 .caretColor("#d4a373")
                 .backgroundColor("#ccd5ae")
                 .hitTestBehavior(HitTestMode.None)
 ​
             Blank()
             Row() {
                 Text("输入长度:").fontColor(Color.Black)
                 Slider({
                     style: SliderStyle.InSet,
                     value: 1,
                     step: 1,
                     min: minStepChar,
                     max: maxStepChar,
                 })
                     .layoutWeight(1)
                     .showSteps(true)
                     .stepSize(3)
                     .showTips(true, `${this.inputStepChar}`)
                     .selectedColor("#f07167")
                     .trackColor("#fdfcdc")
                     .stepColor("#fed9b7")
                     .onChange(value => {
                         this.inputStepChar = value
                         this.inputTxt(this.inputSpeed)
                     })
             }
 ​
             Row() {
                 Text("删除长度:").fontColor(Color.Black)
                 Slider({
                     style: SliderStyle.InSet,
                     value: 1,
                     step: 1,
                     min: minStepChar,
                     max: maxStepChar,
                 })
                     .layoutWeight(1)
                     .showSteps(true)
                     .stepSize(3)
                     .showTips(true, `${this.removeStepChar}`)
                     .selectedColor("#77bfa3")
                     .trackColor("#edeec9")
                     .stepColor("#bfd8bd")
                     .onChange(value => {
                         this.removeStepChar = value
                         this.removeTxt(this.inputSpeed)
                     })
             }
 ​
             Row() {
                 Text("输入速度:").fontColor(Color.Black)
                 Slider({
                     style: SliderStyle.InSet,
                     value: this.defInputSpeed,
                     step: 50,
                     min: minSpeed,
                     max: maxSpeed,
                 })
                     .layoutWeight(1)
                     .showSteps(true)
                     .stepSize(3)
                     .showTips(true, `${this.inputSpeed}`)
                     .selectedColor("#588157")
                     .trackColor("#dad7cd")
                     .stepColor("#a3b18a")
                     .onChange(value => {
                         this.inputSpeed = Math.abs(value - maxSpeed) + minSpeed
                         this.inputTxt(this.inputSpeed)
                     })
             }
 ​
             Row() {
                 Text("删除速度:").fontColor(Color.Black)
                 Slider({
                     style: SliderStyle.InSet,
                     value: this.defRemoveSpeed,
                     step: 50,
                     min: minSpeed,
                     max: maxSpeed,
                 })
                     .layoutWeight(1)
                     .showSteps(true)
                     .stepSize(3)
                     .showTips(true, `${this.removeSpeed}`)
                     .selectedColor("#ddb892")
                     .trackColor("#ede0d4")
                     .stepColor("#e6ccb2")
                     .onChange(value => {
                         this.removeSpeed = Math.abs(value - maxSpeed) + minSpeed
                         this.removeTxt(this.removeSpeed)
                     })
             }
 ​
             Row({ space: 30 }) {
                 Button("输出")
                     .onClick(() => {
                         this.inputTxt(this.inputSpeed)
                     })
                 Button("撤回")
                     .onClick(() => {
                         this.removeTxt(this.removeSpeed)
                     })
             }
         }
         .padding(horizontalBottom(20, 40))
         .size(matchSize)
     }
 }



最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

鸿蒙HarmonyOS Next全套学习资料←点击领取!(安全链接,放心点击

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

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

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

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

HarmonyOS Next 最新全套视频教程

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

大厂面试必问面试题

鸿蒙南向开发技术

鸿蒙APP开发必备

鸿蒙生态应用开发白皮书V2.0PDF

获取以上完整鸿蒙HarmonyOS学习资料,请点击→

纯血版全套鸿蒙HarmonyOS学习资料

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SAP PP学习笔记23 - 生产订单(制造指图)的元素2 - 决济规则(结算规则)

上一章讲了生产订单&#xff08;制造指图&#xff09;画面的基本元素。 SAP PP学习笔记22 - 生产订单&#xff08;制造指图&#xff09;的元素1-CSDN博客 本章继续讲生产订单上面的其他元素。 1&#xff0c;Settlement rule&#xff08;决济规则(结算规则)&#xff09;概要 M…

2024-6-20 Windows AndroidStudio SDK(首次加载)基础配置,SDK选项无法勾选,以及下载失败的一些解决方法

2024-6-20 Windows AndroidStudio SDK(首次加载)基础配置,SDK选项无法勾选,以及下载失败的一些解决方法 注意:仅仅是SDK这种刚安装时的配置的下载,不要和开源库的镜像源扯到一起&#xff01;&#xff01;&#xff01;&#xff01; 最近想玩AndroidStudio的JNI开发, 想着安装后…

02_02_SpringMVC基于注解的应用

一、请求处理 1、常用注解 RequestMapping 作用&#xff1a;用来匹配客户端发送的请求&#xff08;用来处理URL映射&#xff0c;将请求映射到处理方法中&#xff09;&#xff0c;可以在类或者方法上使用。 用在类上&#xff0c;可以将请求模块化&#xff0c;避免请求方法中的…

Linux命令的进程关系

一、shell简述 shell是一个命令行解释器工具&#xff0c;它是一个时刻都在运行的程序&#xff0c;当我们在命令行输入命令&#xff0c;shell会去解释执行这个命令。 shell这个工具不止一种&#xff0c;我们使用Linux系统的时候&#xff0c;默认启动的shell 是/etc/passwd 这个…

超级好用的JSON格式化可视化在线工具

JSON是开发非常常用的一种报文格式&#xff0c;最常见的需求就是将JSON进行格式化&#xff0c;最好是有图形化界面显示结构关系&#xff0c;以便进行数据分析。 理想的在线JSON工具&#xff0c;应该支持快速格式化、可压缩、快捷复制、可下载导出&#xff0c;对存在语法错误的地…

【五】【QT开发应用】C++中lambda表达式,值捕获,引用捕获,隐式捕获,lambda表达式的返回类型

Lambda表达式 复盘 Lambda表达式 Lambda 表达式是 C11 引入的一种特性&#xff0c;用于定义匿名函数。它使得可以在代码中方便地定义和使用小段函数&#xff0c;而无需专门定义一个命名的函数。这在需要传递函数作为参数或者需要定义内联函数时非常有用。 基本语法 基本语法…

Apple - Core Text Programming Guide

本文翻译整理自&#xff1a;Core Text Programming Guide&#xff08;Updated: 2014-09-17 https://developer.apple.com/library/archive/documentation/StringsTextFonts/Conceptual/CoreText_Programming/Introduction/Introduction.html#//apple_ref/doc/uid/TP40005533 文…

docker将容器打包提交为镜像,再打包成tar包

将容器打包成镜像可以通过以下步骤来实现。这里以 Docker 为例&#xff0c;假设你已经安装了 Docker 并且有一个正在运行的容器。 1. 找到正在运行的容器 首先&#xff0c;你需要找到你想要打包成镜像的容器的 ID 或者名字。可以使用以下命令查看所有正在运行的容器&#xff…

高速异地组网怎么办理?

在当今信息化时代&#xff0c;跨地域的远程办公、远程教育、远程医疗等需求越来越多。而高速异地组网作为一种解决不同地区之间快速组建局域网的方法&#xff0c;被广泛应用。本文将介绍一款异地组网内网穿透产品——【天联】&#xff0c;并提供其办理流程。 【天联】组网是什…

【系统设计】如何权衡范式与反范式设计

一、什么是范式设计与反范式设计 1.1、范式设计&#xff08;Normalization&#xff09; 定义&#xff1a; 范式设计是数据库设计中最基础的设计原则之一&#xff0c;它主要通过规范化数据模型&#xff0c;减少数据冗余和数据不一致的问题。 常用的范式&#xff1a; 第一范式…

Android Studio main,xml 视图代码转换

Android Studio main,xml 视图&&代码转换 其实很简单,但是对我们小白来说还是比较蒙的。 废话不多说,直接上图。 我的Android Studio 是 4.0 版的 我刚打开是这个界面,在我想学习如何用代码来布局,可能大家也会找不见代码的位置。 follow me 是不是感觉很简单呢。…

基于DE2-115平台的VGA显示实验

一.任务需求 深入了解VGA协议&#xff0c;理解不同显示模式下的VGA控制时序参数&#xff08;行频、场频、水平/垂直同步时钟周期、显示后沿/前沿等概念和计算方式&#xff09;&#xff1b;通过Verilog编程&#xff0c;在至少2种显示模式下&#xff08;64048060Hz,102476875Hz&…

Day14——Python文本挖掘数据分析

文章目录 竞争分析-品类分布-适用对象竞争分析-产品结构-拜耳在这里插入图片描述竞争分析-产品结构-拜耳-BCG图竞争分析-产品结构-拜耳-明星竞争分析-产品结构-拜耳-奶牛竞争分析-产品结构-拜耳-问题竞争分析-产品结构-安速-BCG图竞争分析-产品结构-安速-明星竞争分析-产品结构…

vue3项目使用Electron打包成exe的方法与打包报错解决

将vue3项目打包成exe文件方法 一、安装 1.安装electron npm install electron --save-devnpm install electron-builder --save-dev 2.在vue项目根目录新建文件index.js // index.js// Modules to control application life and create native browser window const { app…

Python日志管理利器:如何高效管理平台日志

一、为什么需要日志管理&#xff1f; 日志是应用程序的重要组成部分&#xff0c;它记录了应用程序的运行状态、错误信息以及用户交互等关键信息。良好的日志管理可以帮助开发人员及时发现和解决问题&#xff0c;提高应用程序的稳定性和可靠性。 项目在本地开发调试时&#xf…

AGI的多模态融合

在人工智能的宏伟蓝图中&#xff0c;人工通用智能&#xff08;AGI&#xff09;代表着一个集大成者&#xff0c;一个能够理解、学习、适应并执行任何智能任务的系统。随着我们对AGI的探索愈发深入&#xff0c;尤其是在视觉、语言和其他模态的融合上&#xff0c;关于AGI的讨论愈发…

详解DAC数模转换+DAC输出模拟电压的测量比对实验程序

前言&#xff1a;详解DAC数模转换原理DAC输出模拟电压的测量比对实验程序&#xff08;使用 DAC 通道 1 输出模拟电压&#xff0c;然后通过 ADC1 的通道 1 对该输出电压进行读取&#xff0c;并显示在 LCD 模块上面&#xff0c;DAC 的输出电压可以通过按键&#xff08;或 USMART&…

PostgreSQL的学习心得和知识总结(一百四十五)|深入理解PostgreSQL数据库之ShowTransactionState的使用及父子事务有限状态机

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

Kubernetes部署Kanboard看板管理平台

【云原生】Kubernetes部署Kanboard项目管理平台 文章目录 【云原生】Kubernetes部署Kanboard项目管理平台介绍资源列表基础环境一、检查k8s环境1.1、检查工作节点状态1.2、检查系统pod状态 二、编辑kanboard.yaml文件2.1、创建项目目录2.2、编辑kanboard.yaml文件 三、部署Kanb…

Hadoop三大组件原理详解:hdfs-yarn-MapReduce(第9天)

系列文章目录 一、HDFS读写原理【重点】 二、YARN提交mr流程【重点】 三、MapReduce计算流程【重点】 文章目录 系列文章目录前言一、HDFS读写原理[面试]1、HDFS数据写入解析2、HDFS数据读取解析 二、YARN提交mr流程[面试]1. YARN提交mr过程解析 三、MapReduce计算流程[面试]1…