HarmonyOS NEXT Development Case Study: Temperature Conversion Application

The following implementation demonstrates how to create a cross-temperature unit conversion application using HarmonyOS NEXT's declarative development paradigm. This application supports real-time conversion between five temperature units: Celsius, Fahrenheit, Kelvin, Rankine, and Réaumur. Implementation Highlights Modular Temperature Conversion: Utilizes a dedicated temperature conversion module Reactive UI Architecture: Implements observable data models and state management Dynamic Unit Handling: Supports flexible extension of temperature units Input Validation: Ensures numeric input compliance Visual Feedback: Provides real-time UI status indication // Import temperature converter module import { TemperatureConverter } from "@nutpi/temperature-converter" // Define temperature unit type object to store names of each unit const TemperatureUnitType: object = Object({ Celsius: 'Celsius', // Celsius Fahrenheit: 'Fahrenheit', // Fahrenheit Kelvin: 'Kelvin', // Kelvin Rankine: 'Rankine', // Rankine Reaumur: 'Réaumur' // Réaumur }) // Define temperature unit class using decorator @ObservedV2 class TemperatureUnit { title: string // Unit display name @Trace value: string = "" // Current temperature value with trace @Trace isInputFocused: boolean = false // Input focus state tracking constructor(title: string) { this.title = title } // Method to set temperature value with three decimal places setValue(value: number) { this.value = `${parseFloat(value.toFixed(3))}` console.info(`Current value:${this.value}`) } } // Main application entry component @Entry @Component struct TemperatureConverterApp { // Style configuration states @State private primaryColor: string = "#080808" @State private secondaryColor: string = "#f7f7f7" @State private bgColor: string = "#f4f8fb" @State private placeholderColor: string = "#2f9b6c" @State private textColor: string = "#a3a3a3" @State private fontSizeSmall: number = 16 @State private fontSizeLarge: number = 18 @State private basePadding: number = 30 // Initialize temperature unit instances @State private temperatureUnits: TemperatureUnit[] = Object.keys(TemperatureUnitType).map(unit => new TemperatureUnit(TemperatureUnitType[unit])) build() { Column() { // Application title Text('Temperature Converter') .fontColor(this.primaryColor) .fontSize(this.fontSizeSmall) .width('100%') .height(50) .textAlign(TextAlign.Center) .backgroundColor(Color.White) .shadow({ radius: 2, color: this.secondaryColor, offsetX: 0, offsetY: 5 }); // Dynamic input fields Column() { ForEach(this.temperatureUnits, (unit: TemperatureUnit, index: number) => { Row() { Text(`${unit.title}`).fontSize(this.fontSizeSmall).fontColor(this.primaryColor) Row() { TextInput({ text: unit.value, placeholder: !unit.isInputFocused ? `Enter ${unit.title}` : '' }) .inputFilter('[0-9.-]', (e) => console.log(JSON.stringify(e))) .fontSize(this.fontSizeSmall) .backgroundColor(Color.Transparent) .padding(0) .width('100%') .height('100%') .placeholderColor(unit.isInputFocused ? this.placeholderColor : this.textColor) .fontColor(unit.isInputFocused ? this.placeholderColor : this.primaryColor) .caretColor(this.placeholderColor) .borderRadius(0) .onBlur(() => unit.isInputFocused = false) .onFocus(() => unit.isInputFocused = true) .onChange((value: string) => { if (!unit.isInputFocused) return if (unit.value == value) return const tempValue = Number(value); unit.setValue(tempValue) // Conversion logic switch (index) { case 0: this.temperatureUnits[1].setValue(TemperatureConverter.celsiusToFahrenheit(tempValue)) this.temperatureUnits[2].setValue(TemperatureConverter.celsiusToKelvin(tempValue)) this.temperatureUnits[3].setValue(TemperatureConverter.celsiusToRankine(tempValue)) this.temperatureUnits[4].setValue(TemperatureConverter.celsiusToReaumur(tempValue)) break; // Other conversion cases... } }); } .padding(`${this.basePadding / 2}lpx`) .backgroundColor(unit.isInputFocused ? this.bgColor : Color.Transparent) .layoutWeight(1) .height(40) .borderWidth(1) .borderRadius(10) .borderColor(uni

May 11, 2025 - 05:00
 0
HarmonyOS NEXT Development Case Study: Temperature Conversion Application

Image description

The following implementation demonstrates how to create a cross-temperature unit conversion application using HarmonyOS NEXT's declarative development paradigm. This application supports real-time conversion between five temperature units: Celsius, Fahrenheit, Kelvin, Rankine, and Réaumur.

Implementation Highlights

  1. Modular Temperature Conversion: Utilizes a dedicated temperature conversion module
  2. Reactive UI Architecture: Implements observable data models and state management
  3. Dynamic Unit Handling: Supports flexible extension of temperature units
  4. Input Validation: Ensures numeric input compliance
  5. Visual Feedback: Provides real-time UI status indication
// Import temperature converter module
import { TemperatureConverter } from "@nutpi/temperature-converter"

// Define temperature unit type object to store names of each unit
const TemperatureUnitType: object = Object({
  Celsius: 'Celsius',       // Celsius
  Fahrenheit: 'Fahrenheit', // Fahrenheit
  Kelvin: 'Kelvin',         // Kelvin
  Rankine: 'Rankine',       // Rankine
  Reaumur: 'Réaumur'        // Réaumur
})

// Define temperature unit class using decorator
@ObservedV2
class TemperatureUnit {
  title: string             // Unit display name
  @Trace value: string = "" // Current temperature value with trace
  @Trace isInputFocused: boolean = false // Input focus state tracking

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

  // Method to set temperature value with three decimal places
  setValue(value: number) {
    this.value = `${parseFloat(value.toFixed(3))}`
    console.info(`Current value:${this.value}`)
  }
}

// Main application entry component
@Entry
@Component
struct TemperatureConverterApp {
  // Style configuration states
  @State private primaryColor: string = "#080808"
  @State private secondaryColor: string = "#f7f7f7"
  @State private bgColor: string = "#f4f8fb"
  @State private placeholderColor: string = "#2f9b6c"
  @State private textColor: string = "#a3a3a3"
  @State private fontSizeSmall: number = 16
  @State private fontSizeLarge: number = 18
  @State private basePadding: number = 30

  // Initialize temperature unit instances
  @State private temperatureUnits: TemperatureUnit[] =
    Object.keys(TemperatureUnitType).map(unit => new TemperatureUnit(TemperatureUnitType[unit]))

  build() {
    Column() {
      // Application title
      Text('Temperature Converter')
        .fontColor(this.primaryColor)
        .fontSize(this.fontSizeSmall)
        .width('100%')
        .height(50)
        .textAlign(TextAlign.Center)
        .backgroundColor(Color.White)
        .shadow({
          radius: 2,
          color: this.secondaryColor,
          offsetX: 0,
          offsetY: 5
        });

      // Dynamic input fields
      Column() {
        ForEach(this.temperatureUnits, (unit: TemperatureUnit, index: number) => {
          Row() {
            Text(`${unit.title}`).fontSize(this.fontSizeSmall).fontColor(this.primaryColor)

            Row() {
              TextInput({
                text: unit.value,
                placeholder: !unit.isInputFocused ? `Enter ${unit.title}` : ''
              })
                .inputFilter('[0-9.-]', (e) => console.log(JSON.stringify(e)))
                .fontSize(this.fontSizeSmall)
                .backgroundColor(Color.Transparent)
                .padding(0)
                .width('100%')
                .height('100%')
                .placeholderColor(unit.isInputFocused ? this.placeholderColor : this.textColor)
                .fontColor(unit.isInputFocused ? this.placeholderColor : this.primaryColor)
                .caretColor(this.placeholderColor)
                .borderRadius(0)
                .onBlur(() => unit.isInputFocused = false)
                .onFocus(() => unit.isInputFocused = true)
                .onChange((value: string) => {
                  if (!unit.isInputFocused) return
                  if (unit.value == value) return

                  const tempValue = Number(value);
                  unit.setValue(tempValue)

                  // Conversion logic
                  switch (index) {
                    case 0:
                      this.temperatureUnits[1].setValue(TemperatureConverter.celsiusToFahrenheit(tempValue))
                      this.temperatureUnits[2].setValue(TemperatureConverter.celsiusToKelvin(tempValue))
                      this.temperatureUnits[3].setValue(TemperatureConverter.celsiusToRankine(tempValue))
                      this.temperatureUnits[4].setValue(TemperatureConverter.celsiusToReaumur(tempValue))
                      break;
                    // Other conversion cases...
                  }
                });
            }
            .padding(`${this.basePadding / 2}lpx`)
            .backgroundColor(unit.isInputFocused ? this.bgColor : Color.Transparent)
            .layoutWeight(1)
            .height(40)
            .borderWidth(1)
            .borderRadius(10)
            .borderColor(unit.isInputFocused ? this.placeholderColor : this.secondaryColor)
            .margin({ left: `${this.basePadding / 2}lpx`, right: `${this.basePadding / 2}lpx` });
          }.margin({ top: `${this.basePadding / 2}lpx`, bottom: `${this.basePadding / 2}lpx` });
        })
      }
      // UI styling continues...
    }
  }
}

Key Technical Features

  1. Reactive Data Binding:
  2. @ObservedV2 decorator enables automatic UI updates
  3. @Trace implements fine-grained state tracking

  4. Conversion Logic:

  5. Centralized conversion methods from TemperatureConverter module

  6. Chain updating mechanism for dependent units

  7. Input Management:

  8. Focus state tracking for visual feedback

  9. Numeric input validation with regex filter

  10. Styling System:

  11. Centralized style configuration states

  12. Responsive layout using logical pixels (lpx)

  13. Shadow effects and border animations

Usage Scenario

This implementation demonstrates HarmonyOS NEXT's capabilities in:

  • Building complex conversion logic
  • Implementing responsive UI components
  • Managing multi-state interactions
  • Creating professional-grade measurement tools

The architecture allows easy extension to support additional units or conversion types while maintaining clean separation between business logic and UI presentation.