鸿蒙NEXT开发案例:温度转换

 

【引言】

温度是日常生活中常见的物理量,但不同国家和地区可能使用不同的温度单位,如摄氏度(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 库中的方法实现。当用户在某个温度单位的输入框中输入温度后,程序会根据当前输入的温度单位,调用相应的转换方法,计算出其他温度单位对应的值,并更新界面上的显示。

例如,如果用户在摄氏度输入框中输入温度,程序会自动计算出华氏度、开尔文、兰氏度和列氏度的值,并更新相应的输入框。

【用户体验】

为了提升用户体验,我们在输入框上添加了焦点状态的处理。当输入框获得焦点时,背景颜色和边框颜色会发生变化,以提示用户当前的操作位置。此外,输入框还支持输入过滤,只允许输入数字和小数点,确保输入的有效性。

【完整代码】

导包

1
ohpm install @nutpi/temperature-converter

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// 引入温度转换器模块
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); // 设置背景颜色
  }
}

  

posted @   zhongcx  阅读(289)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示