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

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(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
- Reactive Data Binding:
-
@ObservedV2
decorator enables automatic UI updates @Trace
implements fine-grained state trackingConversion Logic:
Centralized conversion methods from
TemperatureConverter
moduleChain updating mechanism for dependent units
Input Management:
Focus state tracking for visual feedback
Numeric input validation with regex filter
Styling System:
Centralized style configuration states
Responsive layout using logical pixels (lpx)
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.