HarmonyOS NEXT Development Case: Counter Application

This article demonstrates how to implement a counter application using HarmonyOS NEXT's ArkUI framework, featuring state management, data persistence, and interactive animations. The application supports multiple counters with customizable steps, swipe actions, and real-time total calculation. Implementation Highlights 1. State Management with Observables @ObservedV2 // Observer decorator to monitor state changes class CounterItem { id: number = ++Index.counterId // Counter ID, auto-incremented @Trace name: string // Counter name @Trace count: number = 0 // Current count value, initial 0 @Trace scale: ScaleOptions = { x: 1, y: 1 } // Scaling factor, initial 1 upStep: number = 1 // Increment step size, initial 1 downStep: number = 1 // Decrement step size, initial 1 constructor(name: string) { // Constructor initializes counter name this.name = name } } 2. Data Persistence @State @Watch('updateTotalCount') counters: CounterItem[] = [] // Counter array with total count watcher aboutToAppear(): void { // Component lifecycle hook const options: preferences.Options = { name: Index.counterStorageKey } this.dataPreferences = preferences.getPreferencesSync(getContext(), options) const savedData: string = this.dataPreferences.getSync(Index.counterStorageKey, "[]") as string const parsedData: Array = JSON.parse(savedData) as Array // Initialize from persisted data parsedData.forEach(item => { const newItem = new CounterItem(item.name) newItem.count = item.count newItem.upStep = item.upStep newItem.downStep = item.downStep this.counters.push(newItem) }) } saveDataToLocal() { // Save counters to Preferences const saveData = this.counters.map(counter => ({ count: counter.count, name: counter.name, upStep: counter.upStep, downStep: counter.downStep })) this.dataPreferences?.putSync(Index.counterStorageKey, JSON.stringify(saveData)) } 3. Interactive UI Components Swipe Actions Implementation: @Builder itemStart(index: number) { // Left swipe action (Reset) Row() { Text('Reset').fontColor(Color.White).fontSize('40lpx') .width('180lpx') } .backgroundColor(Color.Orange) .onClick(() => { this.counters[index].count = 0 this.updateTotalCount() }) } @Builder itemEnd(index: number) { // Right swipe action (Delete) Row() { Text('Delete').fontColor(Color.White).fontSize('40lpx') .width('180lpx') } .backgroundColor(Color.Red) .onClick(() => { this.counters.splice(index, 1) promptAction.showToast({ message: 'Deleted', duration: 2000 }) }) } 4. Animated Counter Operations // Increment animation Stack() { Circle() .width(`${this.baseFontSize}lpx`) .borderColor("#65DACC") .clickEffect({ scale: 0.6 }) .onClick(() => { counter.count += counter.upStep animateTo({ duration: 1000, curve: curves.springCurve(0, 10, 80, 10) }, () => counter.scale = { x: 1, y: 1 }) }) } Core Features Multi-counter Management Add/remove counters with swipe gestures Drag-and-drop reordering Per-counter configuration (name, step sizes) Real-time Synchronization Automatic total calculation using @Watch decorator Instant UI updates through @trace and @ObservedV2 Visual Feedback Spring animations for interactions Custom swipe action indicators Responsive layout adaptation Key Components ListScroller: Manages scroll position for new items preferences.Preferences: Handles data persistence promptAction: Shows system toast notifications curves: Provides spring animation effects Conclusion This implementation demonstrates HarmonyOS NEXT's capabilities in building responsive applications with clean state management and smooth animations. The combination of observable patterns and declarative UI components enables efficient development of complex interactive interfaces. Full source code available with English comments: // Import modules import { curves, promptAction } from '@kit.ArkUI' // Animation curves and toast actions import { preferences } from '@kit.ArkData' // Data persistence module @ObservedV2 // State observer decorator class CounterItem { id: number = ++Index.counterId // Auto-generated counter ID @Trace name: string // Counter display name @Trace count: number = 0 // Current count value @Trace scale: ScaleOptions = { x: 1, y: 1 } // Animation scale upStep: number = 1 // Increment step size downStep: number = 1 // Decrement step size constructor(name: string) { this.name = name } } @Entry // Application entry point @Component // UI component decorator struct Index { // ... } This case showcases essential patterns for HarmonyOS application development, including reactive programming, data persistence, and interactive UI design. Developers can extend this foundation to build more com

May 11, 2025 - 04:26
 0
HarmonyOS NEXT Development Case: Counter Application

Image description

This article demonstrates how to implement a counter application using HarmonyOS NEXT's ArkUI framework, featuring state management, data persistence, and interactive animations. The application supports multiple counters with customizable steps, swipe actions, and real-time total calculation.

Implementation Highlights

1. State Management with Observables

@ObservedV2 // Observer decorator to monitor state changes
class CounterItem {
  id: number = ++Index.counterId // Counter ID, auto-incremented
  @Trace name: string // Counter name
  @Trace count: number = 0 // Current count value, initial 0
  @Trace scale: ScaleOptions = { x: 1, y: 1 } // Scaling factor, initial 1
  upStep: number = 1 // Increment step size, initial 1
  downStep: number = 1 // Decrement step size, initial 1

  constructor(name: string) { // Constructor initializes counter name
    this.name = name
  }
}

2. Data Persistence

@State @Watch('updateTotalCount') counters: CounterItem[] = [] // Counter array with total count watcher

aboutToAppear(): void { // Component lifecycle hook
  const options: preferences.Options = { name: Index.counterStorageKey }
  this.dataPreferences = preferences.getPreferencesSync(getContext(), options)
  const savedData: string = this.dataPreferences.getSync(Index.counterStorageKey, "[]") as string
  const parsedData: Array<CounterItem> = JSON.parse(savedData) as Array<CounterItem>

  // Initialize from persisted data
  parsedData.forEach(item => {
    const newItem = new CounterItem(item.name)
    newItem.count = item.count
    newItem.upStep = item.upStep
    newItem.downStep = item.downStep
    this.counters.push(newItem)
  })
}

saveDataToLocal() { // Save counters to Preferences
  const saveData = this.counters.map(counter => ({
    count: counter.count,
    name: counter.name,
    upStep: counter.upStep,
    downStep: counter.downStep
  }))
  this.dataPreferences?.putSync(Index.counterStorageKey, JSON.stringify(saveData))
}

3. Interactive UI Components

Swipe Actions Implementation:

@Builder
itemStart(index: number) { // Left swipe action (Reset)
  Row() {
    Text('Reset').fontColor(Color.White).fontSize('40lpx')
      .width('180lpx')
  }
  .backgroundColor(Color.Orange)
  .onClick(() => {
    this.counters[index].count = 0
    this.updateTotalCount()
  })
}

@Builder 
itemEnd(index: number) { // Right swipe action (Delete)
  Row() {
    Text('Delete').fontColor(Color.White).fontSize('40lpx')
      .width('180lpx')
  }
  .backgroundColor(Color.Red)
  .onClick(() => {
    this.counters.splice(index, 1)
    promptAction.showToast({ message: 'Deleted', duration: 2000 })
  })
}

4. Animated Counter Operations

// Increment animation
Stack() {
  Circle()
    .width(`${this.baseFontSize}lpx`)
    .borderColor("#65DACC")
    .clickEffect({ scale: 0.6 })
    .onClick(() => {
      counter.count += counter.upStep
      animateTo({
        duration: 1000,
        curve: curves.springCurve(0, 10, 80, 10)
      }, () => counter.scale = { x: 1, y: 1 })
    })
}

Core Features

  1. Multi-counter Management

    • Add/remove counters with swipe gestures
    • Drag-and-drop reordering
    • Per-counter configuration (name, step sizes)
  2. Real-time Synchronization

    • Automatic total calculation using @Watch decorator
    • Instant UI updates through @trace and @ObservedV2
  3. Visual Feedback

    • Spring animations for interactions
    • Custom swipe action indicators
    • Responsive layout adaptation

Key Components

  • ListScroller: Manages scroll position for new items
  • preferences.Preferences: Handles data persistence
  • promptAction: Shows system toast notifications
  • curves: Provides spring animation effects

Conclusion

This implementation demonstrates HarmonyOS NEXT's capabilities in building responsive applications with clean state management and smooth animations. The combination of observable patterns and declarative UI components enables efficient development of complex interactive interfaces.

Full source code available with English comments:

// Import modules
import { curves, promptAction } from '@kit.ArkUI' // Animation curves and toast actions
import { preferences } from '@kit.ArkData' // Data persistence module

@ObservedV2 // State observer decorator
class CounterItem {
  id: number = ++Index.counterId // Auto-generated counter ID
  @Trace name: string // Counter display name
  @Trace count: number = 0 // Current count value
  @Trace scale: ScaleOptions = { x: 1, y: 1 } // Animation scale
  upStep: number = 1 // Increment step size
  downStep: number = 1 // Decrement step size

  constructor(name: string) {
    this.name = name
  }
}

@Entry // Application entry point
@Component // UI component decorator
struct Index {
  // ...  
}

This case showcases essential patterns for HarmonyOS application development, including reactive programming, data persistence, and interactive UI design. Developers can extend this foundation to build more complex applications leveraging HarmonyOS NEXT's full capabilities.