DEV Community

Cover image for HarmonyOS NEXT Development Case: Counter Application
zhongcx
zhongcx

Posted on

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
  }
}
Enter fullscreen mode Exit fullscreen mode

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))
}
Enter fullscreen mode Exit fullscreen mode

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 })
  })
}
Enter fullscreen mode Exit fullscreen mode

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 })
    })
}
Enter fullscreen mode Exit fullscreen mode

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 {
  // ...  
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)