HarmonyOS Next 计时器组件详解

背景介绍

在日常UI开发中,经常会用到计时控件,比如播放视频是的时间进度显示以及音视频通话时显示的通话时长,都需要用到正计时的计时控件。还有些场景会用到倒计时的计时控件,设置一个最大时间,开始倒计时。在Android中我们一般使用TextView,配合Handler来更新TextView实现计时效果。HarmonyOS Next提供了TextTimer组件来实现计时效果。下面先介绍TextTimer能力。

TextTimer 介绍

TextTimer 是一个通过文本显示计时信息并控制其计时器状态的组件。在组件不可见时时间变动将停止,组件的可见状态基于onVisibleAreaChange处理,可见阈值ratios大于0即视为可见状态。

属性介绍
  • format(value: string):设置自定义格式,需至少包含一个HH、mm、ss、SS中的关键字。如使用yy、MM、dd等日期格式,则使用默认值。
  • fontColor(value: ResourceColor):设置字体颜色。
  • fontWeight (value: number | FontWeight | string):设置文本的字体粗细,设置过大可能会在不同字体下有截断。number 类型取值 [100, 900],取值间隔为 100,默认为 400,取值越大,字体越粗。string 类型仅支持 number 类型取值的字符串形式(例如 "400"),以及 "bold"、"bolder"、"lighter"、"regular"、"medium",分别对应 FontWeight 中相应的枚举值。
  • fontFamily (value: ResourceStr):设置字体列表,默认字体为 'HarmonyOS Sans'。应用当前支持 'HarmonyOS Sans' 字体和注册自定义字体,卡片当前仅支持 'HarmonyOS Sans' 字体。
  • textShadow(value: ShadowOptions | Array<ShadowOptions>):设置文字阴影效果,该接口支持以数组形式入参实现多重文字阴影,不支持 fill 字段,不支持智能取色模式。
  • contentModifier(modifier: ContentModifier<TextTimerConfiguration>):定制 TextTimer 内容区的方法,modifier 为内容修改器,开发者需要自定义 class 实现 ContentModifier 接口。

TextTimer构造中需要传入TextTimerOptions对象,TextTimerOptions包含下面属性:

名称 类型 必填 说明
isCountDown boolean 是否倒计时。值为true时,计时器开启倒计时,值为false时,计时器开始计时。 默认值:false
count number 计时器时间(isCountDown为true时生效),单位为毫秒。最长不超过86400000毫秒(24小时)。 0<count<86400000时,count值为计时器初始值。否则,使用默认值为计时器初始值。 默认值:60000
controller TextTimerController TextTimer控制器。

其中TextTimerController 主要用于控制计时器的开启、暂停等:

  • start():计时开始。
  • pause():计时暂停。
  • reset():重置计时器。
事件介绍

主要包含onTimer事件:

  • onTimer (event: (utc: number, elapsedTime: number) => void):时间文本发生变化时触发,锁屏状态和应用后台状态下不会触发该事件。设置高精度的 format(SSS、SS)时,回调间隔可能会出现波动。参数 utc 为 Linux 时间戳,即自 1970 年 1 月 1 日起经过的时间,单位为设置格式的最小单位;elapsedTime 为计时器经过的时间,单位为设置格式的最小单位。

使用示例

示例一:按钮控制计时器
@Entry
@Component
struct TextTimerExample {
  textTimerController: TextTimerController = new TextTimerController()
  @State format: string = 'mm:ss.SS'

  build() {
    Column() {
      TextTimer({ isCountDown: true, count: 30000, controller: this.textTimerController })
        .format(this.format)
        .fontColor(Color.Black)
        .fontSize(50)
        .onTimer((utc: number, elapsedTime: number) => {
          console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)
        })
      Row() {
        Button("start").onClick(() => {
          this.textTimerController.start()
        })
        Button("pause").onClick(() => {
          this.textTimerController.pause()
        })
        Button("reset").onClick(() => {
          this.textTimerController.reset()
        })
      }
    }
  }
}

效果:

示例二:自动执行计时
@Entry
@Component
struct TextTimerStart {
  textTimerController: TextTimerController = new TextTimerController()
  @State format: string = 'mm:ss.SS'

  build() {
    Column() {
      Scroll()
        .height('20%')
      TextTimer({ isCountDown: true, count: 30000, controller: this.textTimerController })
        .format(this.format)
        .fontColor(Color.Black)
        .fontSize(50)
        .onTimer((utc: number, elapsedTime: number) => {
          console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)
        })
        .onAppear(() => {
          this.textTimerController.start()
        })
    }
  }
}

使用局限性

针对正计时场景,每次都是从0开始,有些场景我们期望从某个时间开始计时。比如针对页面切换场景,在视频通话场景,在全屏画面时和悬浮窗时是两个页面,从全屏切换到悬浮窗时希望计时是连续的而不是从0开始,怎么办?

TextTimer提供了内容区域定制的方法:contentModifier,这里需要我们实现一个 ContentModifier<TextTimerConfiguration>

  1. 首先需要实现一个MyTextTimerModifier, applyContent方法中封装Builder方法;
  2. 在自定义Builder方法中自定义UI;
  3. 调用contentModifier将自定义的MyTextTimerModifier实现配置到TextTimer;
  4. 需要删除TextTimer的 颜色和字体配置,通过自定义UI中配置
  5. format设置会影响elapsedTime的单位
  6. config.elapsedTime加一个初始值就实现了从某个时间开始计时
  7. 将秒转换为mm:ss格式

下面是代码示例:

let startTime:number = 100;  
  
function formatData(diffTimeBySecond: number): string {  
  const hours = Math.floor(diffTimeBySecond / 3600);  
  const minutes = Math.floor((diffTimeBySecond % 3600) / 60);  
  const remainingSeconds = Math.floor(diffTimeBySecond % 60);  
  
  // 补零函数  
  const pad = (num: number) => num.toString().padStart(2, '0');  
  
  return hours > 0  
    ? `${pad(hours)}:${pad(minutes)}:${pad(remainingSeconds)}`  
    : `${pad(minutes)}:${pad(remainingSeconds)}`;  
}  
class MyTextTimerModifier implements ContentModifier<TextTimerConfiguration> {  
  constructor() {  
  }  
  applyContent(): WrappedBuilder<[TextTimerConfiguration]> {  
    return wrapBuilder(buildTextTimer)  
  }  
}  
  
@Builder  
function buildTextTimer(config: TextTimerConfiguration) {  
  Column() {  
      Column() {  
        Text(formatData(config.elapsedTime + startTime)).fontColor(Color.Red)  
    }  
  }}  
  
@Entry  
@Component  
struct Index {  
  @State count: number = 10000  
  @State myTimerModifier: MyTextTimerModifier = new MyTextTimerModifier()  
  countUpTextTimerController: TextTimerController = new TextTimerController()  
  
  build() {  
    Row() {  
      Column() {  
        TextTimer({ isCountDown: false, controller: this.countUpTextTimerController })  
          .contentModifier(this.myTimerModifier)  
          .onTimer((utc: number, elapsedTime: number) => {  
            console.info('textTimer onTimer utc is:' + utc + ', elapsedTime: ' + elapsedTime)  
          })  
        Row() {  
          Button("start").onClick(() => {  
            this.countUpTextTimerController.start()  
          }).margin(10)  
          Button("pause").onClick(() => {  
            this.countUpTextTimerController.pause()  
          }).margin(10)  
          Button("reset").onClick(() => {  
            this.countUpTextTimerController.reset()  
          }).margin(10)  
        }.margin(20)  
      }.width('100%')  
    }.height('100%')  
  }  
}

最终效果如下:

相关推荐
别说我什么都不会1 小时前
鸿蒙轻内核M核源码分析系列十七(3) 异常信息ExcInfo
操作系统·harmonyos
kirk_wang2 小时前
HarmonyOS NEXT通过关系型数据库实现数据的持久化
数据库·华为·harmonyos
SameX4 小时前
HarmonyOS Next 中的容器组件——构建灵活页面布局
harmonyos
塞尔维亚大汉19 小时前
OpenHarmony(鸿蒙南向)——平台驱动开发【PIN】
harmonyos·领域驱动设计
Huang兄19 小时前
鸿蒙-自定义相机拍照
华为·harmonyos
鸿蒙开天组●1 天前
鸿蒙实战篇-解决报错提示“code:9568305 error: dependent module does not exist”
华为·编辑器·harmonyos·鸿蒙
SuperHeroWu71 天前
【HarmonyOS Next】拒绝权限二次申请授权处理
华为·harmonyos·授权·设置·弹框·二次申请权限·拒绝权限
m0_748232641 天前
鸿蒙NEXT(五):鸿蒙版React Native架构浅析
react native·架构·harmonyos
东林知识库1 天前
鸿蒙NEXT应用App测试-通用测试
华为·harmonyos