【引言】
溫度是日常生活中常見的物理量,但不同國家和地區可能使用不同的溫度單位,如攝氏度(Celsius)、華氏度(Fahrenheit)、開爾文(Kelvin)、蘭氏度(Rankine)和列氏度(Reaumur)。為了方便使用者在這些溫度單位之間進行快速準確的轉換,我們開發了一款溫度轉換工具。該工具支援五種溫度單位之間的相互轉換,旨在為使用者提供便捷的服務。
【環境準備】
• 作業系統:Windows 10
• 開發工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806
• 目標裝置:華為Mate60 Pro
• 開發語言:ArkTS
• 框架:ArkUI
• API版本:API 12
• 三方庫:@nutpi/temperature-converter(核心演算法)
【專案結構】
專案的核心元件是 TemperatureConverterApp,它負責構建整個應用的使用者介面,並處理使用者輸入及溫度單位之間的轉換邏輯。
1. 溫度單位類定義
我們定義了一個溫度單位類 TemperatureUnit,用於封裝溫度單位的基本資訊及其操作方法。每個溫度單位都有一個標題、當前溫度值和輸入框的焦點狀態。透過 setValue 方法,可以設定溫度值並保留三位小數。
2. 溫度單位型別列舉
為了更好地管理和使用溫度單位,我們定義了一個溫度單位型別物件 TemperatureUnitType,列出了五種溫度單位的名稱。
3. 應用程式主元件
TemperatureConverterApp 元件是整個應用的入口,它定義了應用的樣式屬性,並實現了UI的構建邏輯。元件中包含了多個狀態變數,用於設定應用的顏色、字型大小等樣式。
在UI構建邏輯中,我們使用了鴻蒙NEXT提供的佈局元件,如 Column 和 Row,來組織頁面的佈局。頁面頂部有一個標題 "溫度轉換",下方是一個垂直佈局的容器,動態生成每個溫度單位的輸入框。每個輸入框都繫結了 onChange 事件,當使用者輸入或更改溫度值時,會觸發相應的轉換邏輯,更新其他溫度單位的值。
4. 溫度轉換邏輯
溫度轉換邏輯透過呼叫 @nutpi/temperature-converter 庫中的方法實現。當使用者在某個溫度單位的輸入框中輸入溫度後,程式會根據當前輸入的溫度單位,呼叫相應的轉換方法,計算出其他溫度單位對應的值,並更新介面上的顯示。
例如,如果使用者在攝氏度輸入框中輸入溫度,程式會自動計算出華氏度、開爾文、蘭氏度和列氏度的值,並更新相應的輸入框。
【使用者體驗】
為了提升使用者體驗,我們在輸入框上新增了焦點狀態的處理。當輸入框獲得焦點時,背景顏色和邊框顏色會發生變化,以提示使用者當前的操作位置。此外,輸入框還支援輸入過濾,只允許輸入數字和小數點,確保輸入的有效性。
【完整程式碼】
導包
ohpm install @nutpi/temperature-converter
程式碼
// 引入溫度轉換器模組 import { TemperatureConverter } from "@nutpi/temperature-converter" // 定義溫度單位型別物件,用於儲存各溫度單位的名稱 const TemperatureUnitType: object = Object({ Celsius: '攝氏度', // 攝氏度 Fahrenheit: '華氏度', // 華氏度 Kelvin: '開爾文', // 開爾文 Rankine: '蘭氏度', // 蘭氏度 Reaumur: '列氏度' // 列氏度 }) // 使用裝飾器定義一個溫度單位類 @ObservedV2 class TemperatureUnit { title: string // 溫度單位的標題 @Trace value: string = "" // 當前溫度值,使用@Trace裝飾器追蹤變化 @Trace isInputFocused: boolean = false // 輸入框是否獲得焦點,同樣使用@Trace追蹤變化 // 建構函式,初始化時傳入溫度單位的標題 constructor(title: string) { this.title = title } // 設定溫度值的方法,保留三位小數 setValue(value: number) { this.value = `${parseFloat(value.toFixed(3))}` // 將數值轉換成字串,保留三位小數 console.info(`溫度值:${this.value}`) // 列印當前溫度值到控制檯 } } // 定義溫度轉換器應用程式的入口元件 @Entry @Component struct TemperatureConverterApp { // 定義一系列的狀態變數,用於設定應用的顏色、字型大小等樣式 @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 // 基礎內邊距 // 初始化溫度單位陣列,建立每個溫度單位的例項 @State private temperatureUnits: TemperatureUnit[] = Object.keys(TemperatureUnitType).map(unit => new TemperatureUnit(TemperatureUnitType[unit])) // 構建應用程式的UI build() { Column() { // 建立一個垂直佈局容器 // 新增標題 Text('溫度轉換') .fontColor(this.primaryColor) // 設定字型顏色 .fontSize(this.fontSizeSmall) // 設定字型大小 .width('100%') // 設定寬度 .height(50) // 設定高度 .textAlign(TextAlign.Center) // 設定文字對齊方式 .backgroundColor(Color.White) // 設定背景顏色 .shadow({ // 新增陰影效果 radius: 2, // 陰影半徑 color: this.secondaryColor, // 陰影顏色 offsetX: 0, // X軸偏移量 offsetY: 5 // Y軸偏移量 }); // 迴圈遍歷溫度單位陣列,動態生成每個溫度單位的輸入框 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 ? `請輸入${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) { // 如果輸入框未獲得焦點,則不處理資料 console.info(`當前位置${index}沒有焦點,不處理資料內容`) return } if (unit.value == value) { // 如果新舊值相同,則不處理 console.info(`當前位置${index}內容與修改內容相同,不需要繼續處理`) return } console.info(`onChange, unit.value:${unit.value}, value:${value}`) // 列印變更資訊 const tempValue = Number(value); // 將輸入的字串轉換成數字 unit.setValue(tempValue) // 更新當前溫度單位的值 // 根據使用者輸入的溫度單位,計算並更新其他溫度單位的值 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; case 1: this.temperatureUnits[0].setValue(TemperatureConverter.fahrenheitToCelsius(tempValue)) this.temperatureUnits[2].setValue(TemperatureConverter.fahrenheitToKelvin(tempValue)) this.temperatureUnits[3].setValue(TemperatureConverter.fahrenheitToRankine(tempValue)) this.temperatureUnits[4].setValue(TemperatureConverter.fahrenheitToReaumur(tempValue)) break; case 2: this.temperatureUnits[0].setValue(TemperatureConverter.kelvinToCelsius(tempValue)) this.temperatureUnits[1].setValue(TemperatureConverter.kelvinToFahrenheit(tempValue)) this.temperatureUnits[3].setValue(TemperatureConverter.kelvinToRankine(tempValue)) this.temperatureUnits[4].setValue(TemperatureConverter.kelvinToReaumur(tempValue)) break; case 3: this.temperatureUnits[0].setValue(TemperatureConverter.rankineToCelsius(tempValue)) this.temperatureUnits[1].setValue(TemperatureConverter.rankineToFahrenheit(tempValue)) this.temperatureUnits[2].setValue(TemperatureConverter.rankineToKelvin(tempValue)) this.temperatureUnits[4].setValue(TemperatureConverter.rankineToReaumur(tempValue)) break; case 4: this.temperatureUnits[0].setValue(TemperatureConverter.reaumurToCelsius(tempValue)) this.temperatureUnits[1].setValue(TemperatureConverter.reaumurToFahrenheit(tempValue)) this.temperatureUnits[2].setValue(TemperatureConverter.reaumurToKelvin(tempValue)) this.temperatureUnits[3].setValue(TemperatureConverter.reaumurToRankine(tempValue)) break; } }); } .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` }); // 設定外邊距 }) } .alignItems(HorizontalAlign.Start) // 設定水平對齊方式 .width('650lpx') // 設定寬度 .padding(`${this.basePadding}lpx`) // 設定內邊距 .margin({ top: `${this.basePadding}lpx` }) // 設定外邊距 .borderRadius(10) // 設定圓角 .backgroundColor(Color.White) // 設定背景顏色 .shadow({ // 新增陰影效果 radius: 10, // 陰影半徑 color: this.secondaryColor, // 陰影顏色 offsetX: 0, // X軸偏移量 offsetY: 0 // Y軸偏移量 }); // 新增工具介紹部分 Column() { // 新增標題 Text('工具介紹').fontSize(this.fontSizeLarge).fontWeight(600).fontColor(this.primaryColor); // 新增工具介紹的文字 Text('這款溫度單位轉換工具專為滿足您在科學研究、日常生活及工作中的需求而設計。藉助此工具,您可以輕鬆實現攝氏度(Celsius)、華氏度(Fahrenheit)和開爾文(Kelvin)之間的無縫切換。無論是學術研究、日常應用還是專業工作,都能為您提供精準便捷的溫度換算服務。') .textAlign(TextAlign.JUSTIFY) // 設定文字對齊方式 .fontSize(this.fontSizeSmall) // 設定字型大小 .fontColor(this.primaryColor) // 設定字型顏色 .margin({ top: `${this.basePadding / 2}lpx` }); // 設定外邊距 } .alignItems(HorizontalAlign.Start) // 設定水平對齊方式 .width('650lpx') // 設定寬度 .padding(`${this.basePadding}lpx`) // 設定內邊距 .margin({ top: `${this.basePadding}lpx` }) // 設定外邊距 .borderRadius(10) // 設定圓角 .backgroundColor(Color.White) // 設定背景顏色 .shadow({ // 新增陰影效果 radius: 10, // 陰影半徑 color: this.secondaryColor, // 陰影顏色 offsetX: 0, // X軸偏移量 offsetY: 0 // Y軸偏移量 }); } .height('100%') // 設定高度 .width('100%') // 設定寬度 .backgroundColor(this.bgColor); // 設定背景顏色 } }