首页 > 其他分享 >梅科尔工作室HOS-鸿蒙开发实战(深呼吸)

梅科尔工作室HOS-鸿蒙开发实战(深呼吸)

时间:2024-02-06 11:04:12浏览次数:27  
标签:鸿蒙 Text number height State fontSize HOS 深呼吸 fontColor

页面整体展示效果

梅科尔工作室HOS-鸿蒙开发实战(深呼吸)_星计划

源码

import http from '@ohos.net.http'  
@Entry  
@Component  
struct jieya {  
  textTimerController: TextTimerController = new TextTimerController()  
  @State isTimerRunning: boolean = true // 新增一个状态变量来表示计时器运行状态  
  @State format: string = 'HH:mm:ss'  
  @State audioSrc: Resource = $rawfile("shuhuanyinyue.mp3"); //音频路径  
  @State isAutoPlay: boolean = false; //是否自动播放  
  @State autoPlay:boolean = false;//是否自动播放  
  @State loop:boolean = true;//是否循环播放  
  @State huxicishu: number=0  
  
  
  videoController: VideoController = new VideoController();//导入对象  
  
  @State textValue: string = ''  
  @State inputValue: string = 'click me'  
  @State hours : number=0  
  @State minutes : number=0  
  @State seconds : number=0  
  
  controller: TextClockController = new TextClockController()  
  dialogController: CustomDialogController = new CustomDialogController({  
    builder: CustomDialogExample({  
      cancel: this.onCancel,  
      confirm: this.onAccept,  
      hours:$hours,  
      minutes:$minutes,  
      seconds:$seconds,  
      huxicishu:$huxicishu,  
    }),  
    cancel: this.existApp,  
    autoCancel: true,  
    alignment: DialogAlignment.Center,  
    offset: { dx: 0, dy: -20 },  
    gridCount: 3,  
    customStyle: false  
  })  
  // 在自定义组件即将析构销毁时将dialogController置空  
  aboutToDisappear() {  
    this.dialogController = undefined // 将dialogController置空  
  }  
  
  onCancel() {  
    console.info('Callback when the first button is clicked')  
  }  
  
  onAccept() {  
    console.info('Callback when the second button is clicked')  
  }  
  
  existApp() {  
    console.info('Click the callback in the blank area')  
  }  
  build(){  
    Row() {  
      Column() {  
        Stack() {  
          Image($r('app.media.huxibeijing'))  
  
          Column({space:40}) {  
            Stack() {  
              Column()  
                .height(180)  
                .width(180)  
                .borderRadius(90)  
                .backgroundColor("#FFFFFF")  
                .opacity(0.71)  
              TextTimer({ controller: this.textTimerController, isCountDown: false, count: 30000 })  
                .format(this.format)  
                .fontColor(Color.Black)  
                .fontSize(35)  
                .onTimer((utc: number, elapsedTime: number) => {  
                  console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)  
                  this.huxicishu=parseInt((this.seconds/5).toString())  
                  this.hours = parseInt((elapsedTime % (1000 * 60 * 60 * 24) / (1000 * 60 * 60)).toString());  
                  this.minutes = parseInt((elapsedTime % (1000 * 60 * 60) / (1000 * 60)).toString());  
                  this.seconds = parseInt((elapsedTime% (1000 * 60) / 1000).toString());  
                })  
            }  
  
            Video({  
              src: this.audioSrc,  
              controller: this.videoController  
            }).height(0)  
              .autoPlay(this.isAutoPlay)  
            Column({space:20}) {  
              Button("开始呼吸")  
                .width(150)  
                .height(50)  
                .fontColor("#636B60")  
                .fontSize(18)  
                .backgroundColor("white")  
                .borderRadius(15)  
                .onClick(() => {  
                  this.textTimerController.start()  
                  this.videoController.start();  
                  this.controller.start()  
                })  
              Button("结束呼吸")  
                .width(150)  
                .height(50)  
                .fontColor("#636B60")  
                .fontSize(18)  
                .backgroundColor("white")  
                .borderRadius(15)  
                .onClick(() => {  
                  this.textTimerController.reset()  
                  this.videoController.stop()  
                  this.controller.stop()  
                  if (this.dialogController != undefined) {  
                    this.dialogController.open()  
                  }  
                })  
              Button("历史记录")  
                .width(150)  
                .height(50)  
                .fontColor("#636B60")  
                .fontSize(18)  
                .backgroundColor("white")  
                .borderRadius(15)  
                .onClick(() => {  
                  this.textTimerController.pause()  
                  this.videoController.pause();  
                })  
            }  
          }.width("100%").height("100%")  
        }  
  
      }    }  }}

项目架构

main
├─ module.json5
├─ resources
│  ├─ zh_CN
│  ├─ media        //图片资源目录
│  ├─ rawfile        //音频资源目录
│  └─ base
└─ ets
   ├─ pages
   │  └─ Index.ets          //主页面
   └─ entryability
      └─ EntryAbility.ts

1.背景音乐的设置

我们使用官方用于播放视频文件并控制其播放状态的组件Video进行开发

首先进行变量的声明

@State videoSrc: Resource = $rawfile("shuhuanyinyue.mp3"); //音频路径  
@State isAutoPlay: boolean = false; //是否自动播放     
@State autoPlay:boolean = false;//是否自动播放  
@State loop:boolean = true;//是否循环播放

导入对象

videoController: VideoController = new VideoController();

使用Video组件,设置其高度为0,路径为声明的音频路径

Video({  
  src: this.audioSrc,  
  controller: this.videoController
}).height(0)  
  .autoPlay(this.isAutoPlay)

点击开始呼吸按钮,背景音乐开始播放,点击结束按钮,背景音乐停止

Column({space:20}) {  
  Button("开始呼吸")  
    .width(150)  
    .height(50)  
    .fontColor("#636B60")  
    .fontSize(18)  
    .backgroundColor("white")  
    .borderRadius(15)  
    .onClick(() => {  
      this.videoController.start();  
    })  
  Button("结束呼吸")  
    .width(150)  
    .height(50)  
    .fontColor("#636B60")  
    .fontSize(18)  
    .backgroundColor("white")  
    .borderRadius(15)  
    .onClick(() => {  
      this.videoController.stop()  
    })  
}

2.计时器的使用

首先声明format变量,计时器以小时、分钟、秒的形式进行计时

@State format: string = 'HH:mm:ss'

导入计时器对象

textTimerController: TextTimerController = new TextTimerController()

使用TextTimer组件显示计时器信息并控制计时器的状态

TextTimer({ controller: this.textTimerController, isCountDown: false, count: 30000 })  
  .format(this.format)  
  .fontColor(Color.Black)  
  .fontSize(35)  
  .onTimer((utc: number, elapsedTime: number) => {  
    console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)  
  })

点击开始呼吸按钮,计时器开始计时,点击结束呼吸按钮,计时器结束计时并清0

Button("开始呼吸")  
  .width(150)  
  .height(50)  
  .fontColor("#636B60")  
  .fontSize(18)  
  .backgroundColor("white")  
  .borderRadius(15)  
  .onClick(() => {  
    this.textTimerController.start()  
  })  
Button("结束呼吸")  
  .width(150)  
  .height(50)  
  .fontColor("#636B60")  
  .fontSize(18)  
  .backgroundColor("white")  
  .borderRadius(15)  
  .onClick(() => {  
    this.textTimerController.reset()  
  })

3.自定义弹窗

在父组件中进行对话框的构建、显示和控制以及对话框内的文本内容和状态的更新。

controller: TextClockController = new TextClockController()  
dialogController: CustomDialogController = new CustomDialogController({  
  builder: CustomDialogExample({  
    cancel: this.onCancel,  
    confirm: this.onAccept,  
    textValue: $textValue,  
    inputValue: $inputValue,  
    cot:$cot,  
    hours:$hours,  
    minutes:$minutes,  
    seconds:$seconds,  
    milliseconds:$milliseconds,  
    huxicishu:$huxicishu,  
  }),  
  cancel: this.existApp,  
  autoCancel: true,  
  alignment: DialogAlignment.Center,  
  offset: { dx: 0, dy: -20 },  
  gridCount: 3,  
  customStyle: false  
})

在子组件进行弹窗UI页面的编写,代码如下

@CustomDialog  
struct CustomDialogExample {  
  
  @Link huxicishu: number  
  @Link hours : number  
  @Link minutes : number  
  @Link seconds : number  
  controller: CustomDialogController  
  // 若尝试在CustomDialog中传入多个其他的Controller,以实现在CustomDialog中打开另一个或另一些CustomDialog,那么此处需要将指向自己的controller放在最后  
  cancel: () => void  
  confirm: () => void  
  build(){  
    Stack(){  
      Image($r("app.media.tanchuangbeijing")).height(290).borderRadius(20)  
      Column({space:12}){  
        Row(){  
          Image($r("app.media.huxijieguo")).height(45).width(50)  
          Text("呼吸结果").fontSize(22)  
        }  
        Text("恭喜你又完成一次呼吸!").fontSize(12).fontColor("#4C5250")  
        Divider().vertical(false).strokeWidth(1).color("#BBBBBB").lineCap(LineCapStyle.Round).width(200)  
        Row(){  
          Image($r("app.media.huxicishu")).height(40).width(36)  
          Text("呼吸次数:").fontSize(14)  
          Text(this.huxicishu.toString()).fontSize(22).fontColor("#C21818")  
          Text("次").fontSize(14)  
        }  
        Row(){  
          Image($r("app.media.huxishichang")).height(40).width(36)  
          Text("呼吸时长:").fontSize(14)  
          Text(this.hours.toString()).fontSize(22).fontColor("#C21818")  
          Text("h").fontSize(18)  
          Text(this.minutes.toString()).fontSize(22).fontColor("#C21818")  
          Text("min").fontSize(18)  
          Text(this.seconds.toString()).fontSize(22).fontColor("#C21818")  
          Text("s").fontSize(19)  
        }  
  
        Flex({ justifyContent: FlexAlign.SpaceAround }) {  
          Button('我知道了')  
            .onClick(() => {  
              this.controller.close()  
              this.cancel()  
            }).backgroundColor("#59C8FD").fontColor(Color.White).height(35).width(128)  
        }  
      }    }  }}

4.将计时器计时到的数据传到弹窗界面

首先使用@State声明变量并进行初始化

@State hours : number=0  
@State minutes : number=0  
@State seconds : number=0

获取计时器计时的时间 elapsedTime,单位为毫秒。然后将该时间转换成小时分钟秒的形式。

this.hours = parseInt((elapsedTime % (1000 * 60 * 60 * 24) / (1000 * 60 * 60)).toString());  
this.minutes = parseInt((elapsedTime % (1000 * 60 * 60) / (1000 * 60)).toString());  
this.seconds = parseInt((elapsedTime% (1000 * 60) / 1000).toString());

子组件使用@Link装饰器将hours、minutes、seconds、milliseconds这些状态变量与父组件传递的相应变量进行关联,以便在对话框中显示和更新这些值。

@Link hours : number  
  @Link minutes : number  
  @Link seconds : number

在子组件弹窗组件对应位置对计时到的数据进行调用

Row(){  
  Image("/common/images/huxishichang.png").height(40).width(36)  
  Text("呼吸时长:").fontSize(14)  
  Text(this.hours.toString()).fontSize(22).fontColor("#C21818")  
  Text("h").fontSize(18)  
  Text(this.minutes.toString()).fontSize(22).fontColor("#C21818")  
  Text("min").fontSize(18)  
  Text(this.seconds.toString()).fontSize(22).fontColor("#C21818")  
  Text("s").fontSize(19)  
}

5.总结

该页面使用鸿蒙开发的主力语言——ArkTS语言进行开发,完成了页面的布局、元素控制以及逻辑控制等。该实践内容主要供用户进行解压放松,点击开始呼吸按钮,开始播放背景音乐,用户深呼吸进行放松,同时计时器也开始计时,点击结束呼吸按钮,背景音乐和计时器都停止,同时自定义弹窗出现,该弹窗展示了用户本次呼吸时长以及呼吸次数等。

本次开发是一次很不错的体验,使我了解了ArkTS语言在鸿蒙开发中以其独特的特点和优势。后续我也会不断学习和探索,也期待着与更多的开发者一起共同探讨和实践鸿蒙开发技术。

本文作者:梅科尔吴玉佩

想了解更多关于鸿蒙的内容,请访问:

51CTO鸿蒙开发者社区

https://ost.51cto.com/#bkwz


标签:鸿蒙,Text,number,height,State,fontSize,HOS,深呼吸,fontColor
From: https://blog.51cto.com/harmonyos/9617570

相关文章

  • 【转帖】localhost和127.0.0.1的区别
    plantegg.github.io/2023/09/24/localhost和127.0.0.1的区别/背景有人告诉我localhost和127.0.0.1的区别是localhost不经过网卡,把我惊到了,因为我还真不知道这个知识点,于是去特别去验证了一下,这是个错误的理解,localhost会解析成127.0.0.1然后接下来的流程和127.0.0.1一模一......
  • openharmony4.0 实现网络 app, 鸿蒙
    问题:拿到了开发者手机,但是再测试网络部分的时候出现问题。记录一下。 解决:需要再应用中对网络进行配置,便可以直接复制官方文档中的例子。 1官方文档的路径。https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-http.md......
  • 鸿蒙:揭晓 ArkTS,重塑语法,打造更健壮和可靠的代码
    hi大家好,我是DHL。就职于美团、快手、小米。公众号:ByteCode,分享有用的原创文章,涉及鸿蒙、Android、Java、Kotlin、性能优化、大厂面经我最近建了一个鸿蒙开发者交流群,群里有大佬说在gitee鸿蒙仓库中可以下载DevEcoStudio4.0。于是我下载体验了一下,运行了官方提供示例项目Sh......
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TimePicker组件
    鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TimePicker组件一、操作环境操作系统: Windows10专业版、IDE:DevEcoStudio3.1、SDK:HarmonyOS3.1+编辑二、TimePicker组件TextClock组件通过文本将当前系统时间显示在设备上。支持不同时区的时间显示,最高精度到秒级。子组件无。接口TimePic......
  • 鸿蒙开发有必要学吗?看完这篇再决定吧
    在科技的潮流中,每一次新操作系统的诞生都是对旧秩序的挑战与新机遇的孕育。鸿蒙操作系统的出现,无疑是近年来科技界最引人注目的事件之一。自华为于2019年正式推出鸿蒙系统以来,这一我们自主研发的操作系统不仅在国内引起巨大反响,更在全球范围内展示了中国科技的崛起。鸿蒙系统最初......
  • 盘点那些硬件+项目学习套件:Hi3861鸿蒙开发板及入门常见问题解答
    华清远见20岁了~过去3年里,华清远见研发中心针对个人开发板业务,打造了多款硬件+项目学习套件,涉及STM32单片机、嵌入式、物联网、人工智能、鸿蒙、ESP32、阿里云IoT等多技术方向。今天我们来盘点一下,比较受欢迎几款“硬件+项目”学习套件,以及一些初学者比较关注的问题。盘点二:Hi3861......
  • OpenWrt之自定义Hostname
    OpenWrt之自定义Hostname找到对应的代码,在feeds/./luci/modules/luci-lua-runtime/luasrc/sys.lua中,有cur:foreach("dhcp","dnsmasq",function(s)ifs.leasefileandfs.access(s.leasefile)then......
  • 【鸿蒙千帆起】高德地图携手HarmonyOS NEXT,开启智能出行新篇章
    2024年1月18日下午,华为举办了鸿蒙生态千帆启航仪式,对外宣布HarmonyOSNEXT星河预览版现已开放申请,同时,首批200+鸿蒙原生应用加速开发,鸿蒙生态设备数量更是突破了8亿大关。这些进展反映了开发者和合作伙伴对鸿蒙生态未来发展的坚定信心和美好期待。1月19日HarmonyOS应用开发技术分......
  • 主机--Host
    概念:主机是用于构建应用程序和服务、封装应用资源的对象,负责程序的启动和生命周期的管理,简单来说主机即应用程序。主机运行:当主机运行的时候,他会将托管在服务容器集合里面注册的IHostService的每个实现调用IHostService.StartAsync()。在web应用中,每一个IHostService实现就是启动......
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TextClock组件
    鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TextClock组件一、操作环境操作系统: Windows10专业版、IDE:DevEcoStudio3.1、SDK:HarmonyOS3.1+编辑二、TextClock组件TextClock组件通过文本将当前系统时间显示在设备上。支持不同时区的时间显示,最高精度到秒级。子组件无。接口TextClock......