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.