Detailed Explanation of HarmonyOS Next Timer Component
Background Introduction
In daily UI development, timer controls are frequently used. For example, time progress display during video playback and call duration display in audio/video calls require forward-counting timer controls. In some scenarios, countdown timer controls are needed, where a maximum time is set to start the countdown. In Android, we typically use TextView
combined with Handler
to update the TextView
for timing effects. HarmonyOS Next provides the TextTimer
component to achieve timing effects. Below is an introduction to the capabilities of TextTimer
.
Introduction to TextTimer
TextTimer
is a component that displays timing information through text and controls its timer state. When the component is invisible, time changes will stop. The visibility state of the component is handled based on onVisibleAreaChange
, and a visibility threshold ratio greater than 0 is considered visible.
Attribute Introduction
-
format(value: string)
: Sets a custom format, which must include at least one keyword from HH, mm, ss, or SS. If date formats like yy, MM, or dd are used, default values will apply. -
fontColor(value: ResourceColor)
: Sets the font color. -
fontWeight(value: number | FontWeight | string)
: Sets the font weight of the text. Excessively large values may cause truncation in different fonts. For the number type, values range from[100, 900]
with an interval of 100 (default is 400); larger values make the font bolder. The string type supports numeric string forms (e.g., "400") and keywords like "bold", "bolder", "lighter", "regular", and "medium", corresponding to the respective enumeration values inFontWeight
. -
fontFamily(value: ResourceStr)
: Sets the font list, with the default font being 'HarmonyOS Sans'. Applications currently support 'HarmonyOS Sans' and registered custom fonts, while cards only support 'HarmonyOS Sans'. -
textShadow(value: ShadowOptions | Array<ShadowOptions>)
: Sets text shadow effects. This interface supports array parameters for multiple shadows, but does not support thefill
field or intelligent color pickup mode. -
contentModifier(modifier: ContentModifier<TextTimerConfiguration>)
: A method to customize the content area ofTextTimer
, wheremodifier
is a content modifier that developers need to implement by defining a class that adheres to theContentModifier
interface.
The TextTimer
constructor requires a TextTimerOptions
object, which includes the following attributes:
Name | Type | Required | Description |
---|---|---|---|
isCountDown | boolean | No | Indicates whether to use countdown. When true , the timer starts counting down; when false , it starts counting up.Default: false
|
count | number | No | Timer duration (effective when isCountDown is true ), in milliseconds. The maximum duration is 86,400,000 milliseconds (24 hours). When 0 < count < 86,400,000 , count is the initial timer value; otherwise, the default value is used.Default: 60000
|
controller | TextTimerController | No | The TextTimer controller, used to start, pause, etc. |
The TextTimerController
mainly controls the timer:
-
start()
: Starts the timer. -
pause()
: Pauses the timer. -
reset()
: Resets the timer.
Event Introduction
The main event is onTimer
:
-
onTimer(event: (utc: number, elapsedTime: number) => void)
: Triggered when the time text changes. This event is not triggered when the screen is locked or the app is in the background. When setting high-precision formats (SSS, SS), the callback interval may fluctuate. The parameterutc
is a Linux timestamp (time elapsed since January 1, 1970) in the minimum unit of the set format;elapsedTime
is the elapsed time of the timer, also in the minimum unit of the set format.
Usage Examples
Example 1: Button-Controlled Timer
@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()
})
}
}
}
}
Example 2: Automatic Timing
@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()
})
}
}
}
Usage Limitations
For forward-counting scenarios, the timer always starts from 0, but some scenarios require starting from a specific time. For example, in page switching during a video call, the full-screen and floating-window pages should have continuous timing instead of restarting from 0. How to achieve this?
TextTimer
provides a content area customization method contentModifier
, which requires implementing ContentModifier<TextTimerConfiguration>
:
- First, implement
MyTextTimerModifier
and encapsulate theBuilder
method in theapplyContent
method. - Customize the UI in the custom
Builder
method. - Configure the custom
MyTextTimerModifier
toTextTimer
usingcontentModifier
. - Remove color and font configurations from
TextTimer
and configure them in the custom UI. - The
format
setting affects the unit ofelapsedTime
. - Adding an initial value to
config.elapsedTime
starts timing from a specific time. - Convert seconds to the
mm:ss
format.
Code example:
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);
// Zero-padding function
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%')
}
}
Top comments (0)