简约之美:开发计时器应用——在精确倒计时中感受时间的流转之美(2) 原创

醉丶斛觞
发布于 2024-11-7 18:27
浏览
0收藏

倒计时Gif效果

简约之美:开发计时器应用——在精确倒计时中感受时间的流转之美(2)-鸿蒙开发者社区

昨天,我以轻松的姿态投入了编程的战场,为我的计时器应用添上了正计时这一基础功能。而今天,我更是全力以赴,为应用注入了倒计时这一亮点。在这个过程中,我深刻体会到了技术设计的巧妙,简单的代码也能塑造出强大的应用能力。

正计时功能,就像是篮球比赛中的计时器,虽然它在后台默默工作,但它的存在不可或缺。想象你是一位篮球运动员,在每一次训练和比赛中,正计时器记录着你的每一滴汗水,它是你努力付出的见证。

然而,倒计时功能才是这场时间管理游戏的真正主角。想象你站在百米赛跑的起跑线上,倒计时器就像是你心中的发令枪,它提醒你每一刻的重要性和紧迫性。设置一个倒计时,它会在关键时刻响起,确保你能够从容不迫地完成热身,并在枪响的那一刻爆发出全部的力量。

在构建这个计时器时,我们采用了HarmonyOS NEXT的TextTimer组件,它的流畅性让我们的开发过程如鱼得水。以下是我对这次开发的一些心得体会:

正计时器的开发,就像是球场上的即兴表演,快速而直接。用户通过简洁的界面操作,就能轻松管理时间的流逝,让每一秒都变得可控。

倒计时器的开发,则像是精心编排的赛事策略,每一个细节都至关重要。用户可以自定义倒计时的时间,当倒计时结束时,计时器会自动发出提醒,确保用户不会错过任何一个关键时刻。我们不断优化这一功能,力求在用户的每一次使用中,都能感受到便捷与完美。虽然目前我们还未深入挖掘HarmonyOS NEXT的全部潜力,但我相信,随着开发的深入,我们的计时器将变得更加精准和高效。

代码示例

自定义封装弹窗


@CustomDialog
export struct TimerDialog {
  controller?: CustomDialogController
  selectedTime: Date = initDate();
  currentFileName: string = 'TimerDialog'
  @State date: TimePickerResult | undefined = undefined
  onConfirm: (date: TimePickerResult | undefined) => TimePickerResult | undefined =
    (date: TimePickerResult | undefined) => {
      return date;
    }
  onCancle: () => void = () => {
  }

  build() {
    Column() {
      Text('设置倒计时')
        .fontSize(24)
        .margin(30)
      TimePicker({
        selected: this.selectedTime, format: TimePickerFormat.HOUR_MINUTE_SECOND
      })
        .useMilitaryTime(true)
        .onChange((date: TimePickerResult) => {
          this.date = date
          console.info('select current date is: ' + JSON.stringify(date))
        })


      Row() {
        Button('确定')
          .padding({ left: 30, right: 30 })
          .onClick(() => {
            this.onConfirm(this.date)
          })
        Button('取消')
          .padding({ left: 30, right: 30 })
          .onClick(() => {
            this.onCancle()
          })
      }
      .width('100%')
      .margin(30)
      .justifyContent(FlexAlign.SpaceAround)
    }.width('100%')
  }
}

export function initDate(): Date {
  let date = new Date();
  date.setHours(0);
  date.setMinutes(0);
  date.setSeconds(0);

  return date;
}

ArkTS 交互逻辑

// 自定义弹窗的回调函数及相关参数
dialogController: CustomDialogController = new CustomDialogController({
    builder: TimerDialog({
      onConfirm: (date: TimePickerResult | undefined) => {
        this.dialogController.close()
        if (date) {
          this.millSeconds = date.hour * 3600000 + date.minute * 60000 + date.second * 1000;
        }
        return date;
      },
      onCancle: () => {
        animateTo({ duration: 200 }, () => {
          this.countMode = !this.countMode;
          this.dialogController.close()
        })
      }
    })
  })

 // UI 交互
 Text(this.countMode ? this.countUp : this.countDown)
        .fontColor(Color.Blue)
        .fontColor(28)
        .onClick(() => {
          this.countMode = !this.countMode
          if (this.countMode) {
            this.textTimerController.reset()
          }
          if (!this.countMode) {
            this.millSeconds = 0;
            this.dialogController.open()
          }
        })
        .borderWidth({ bottom: 1 })

通过触发弹窗的 open() 方法,我们展示了弹窗界面供用户进行选择。一旦用户选择了日期,我们便可以利用回调函数来执行毫秒级的换算操作,进而更新 TextTimer 倒计时组件,确保其显示与用户所选日期同步。

核心UI结构

@Component
@Entry
export struct ClockDemo1 {
  textTimerController: TextTimerController = new TextTimerController()
  @State countMode: boolean = true
  countUp: string = '正计时 => 倒计时';
  countDown: string = '倒计时 => 正计时'
  @State millSeconds: number = -1;
  dialogController: CustomDialogController = new CustomDialogController({
    builder: TimerDialog({
      onConfirm: (date: TimePickerResult | undefined) => {
        this.dialogController.close()
        if (date) {
          this.millSeconds = date.hour * 3600000 + date.minute * 60000 + date.second * 1000;
        }
        return date;
      },
      onCancle: () => {
        animateTo({ duration: 200 }, () => {
          this.countMode = !this.countMode;
          this.dialogController.close()
        })
      }
    })
  })

  build() {
    Column() {
      Text(this.countMode ? this.countUp : this.countDown)
        .fontColor(Color.Blue)
        .fontColor(28)
        .onClick(() => {
          this.countMode = !this.countMode
          if (this.countMode) {
            this.textTimerController.reset()
          }
          if (!this.countMode) {
            this.millSeconds = 0;
            this.dialogController.open()
          }
        })
        .borderWidth({ bottom: 1 })

      Row() {
        if (this.countMode) {
          TextTimer({
            controller: this.textTimerController,
          })
            .fontSize(120)
            .format('HH:mm:ss')
        } else {
          TextTimer({
            controller: this.textTimerController,
            count: this.millSeconds,
            isCountDown: true
          })
            .fontSize(120)
            .format('HH:mm:ss')
        }
      }
      .borderWidth(1)
      .borderRadius(30)

      Row() {
        TextButton({ text: '启动' })
          .onClick(() => {
            this.textTimerController.start()
          })
        TextButton({ text: '暂停' })
          .onClick(() => {
            this.textTimerController.pause()
          })
        TextButton({ text: '重置' })
          .onClick(() => {
            this.textTimerController.reset()
          })
      }
      .width('50%')
      .justifyContent(FlexAlign.SpaceEvenly)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.SpaceEvenly)
  }
}

@Component
struct TextButton {
  text: string = '文本按钮'

  build() {
    Row() {
      Text(this.text)
        .margin(5)
    }
    .borderWidth(1)
    .width(80)
    .borderRadius(100)
    .justifyContent(FlexAlign.Center)
    .alignItems(VerticalAlign.Center)

  }
}


@CustomDialog
export struct TimerDialog {
  controller?: CustomDialogController
  selectedTime: Date = initDate();
  currentFileName: string = 'TimerDialog'
  @State date: TimePickerResult | undefined = undefined
  onConfirm: (date: TimePickerResult | undefined) => TimePickerResult | undefined =
    (date: TimePickerResult | undefined) => {
      return date;
    }
  onCancle: () => void = () => {
  }

  build() {
    Column() {
      Text('设置倒计时')
        .fontSize(24)
        .margin(30)
      TimePicker({
        selected: this.selectedTime, format: TimePickerFormat.HOUR_MINUTE_SECOND
      })
        .useMilitaryTime(true)
        .onChange((date: TimePickerResult) => {
          this.date = date
          console.info('select current date is: ' + JSON.stringify(date))
        })


      Row() {
        Button('确定')
          .padding({ left: 30, right: 30 })
          .onClick(() => {
            this.onConfirm(this.date)
          })
        Button('取消')
          .padding({ left: 30, right: 30 })
          .onClick(() => {
            this.onCancle()
          })
      }
      .width('100%')
      .margin(30)
      .justifyContent(FlexAlign.SpaceAround)
    }.width('100%')
  }
}

export function initDate(): Date {
  let date = new Date();
  date.setHours(0);
  date.setMinutes(0);
  date.setSeconds(0);

  return date;
}

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
收藏
回复
举报
回复
    相关推荐