代码功能概述
这段代码实现了一个功能完整的鸿蒙单位转换器应用,全面展示了ArkTS在表单处理、数据计算和分类管理等方面的核心能力。主要功能包括:
- 多分类单位转换:支持长度、重量、温度、面积四种单位类型的转换
- 实时计算:输入数值或切换单位时立即显示转换结果
- 智能输入验证:确保用户输入为有效数字
- 单位交换功能:一键交换源单位和目标单位
- 格式化显示:智能格式化计算结果,移除不必要的尾随零
- 温度特殊处理:针对温度单位使用专用转换公式
代码逻辑分析
应用采用"状态驱动UI"的现代化架构设计:
1. 初始化阶段:应用启动时,通过`aboutToAppear()`生命周期方法进行初始计算
2. 状态管理:使用多个`@State`装饰器管理输入值、分类选择、单位选择和计算结果
3. 用户交互流程:
- 选择分类 → 更新`selectedCategory` → 重置单位选择并重新计算
- 输入数值 → 验证并更新`inputValue` → 触发实时计算
- 切换单位 → 更新`fromUnit`或`toUnit` → 重新计算转换结果
- 点击交换按钮 → 交换源目标和目标单位 → 更新计算结果
4. 数据计算:根据单位类型使用不同的转换算法,普通单位使用系数转换,温度单位使用专用公式
5. UI自动更新:所有状态变化自动触发界面重新渲染,实现即时反馈
完整代码
// 鸿蒙单位转换器 - UnitConverterTutorial.ets
// 本应用演示ArkTS的表单处理、数据计算和分类管理
@Entry
@Component
struct UnitConverterTutorial {
// @State装饰器:管理转换器状态
@State inputValue: string = '1';
@State selectedCategory: number = 0;
@State fromUnit: number = 0;
@State toUnit: number = 1;
@State result: string = '';
@State isReversed: boolean = false;
// 单位分类数据
private categories: Category[] = [
{
name: '长度',
units: ['米', '厘米', '毫米', '千米', '英尺', '英寸'],
factors: [1, 100, 1000, 0.001, 3.28084, 39.3701]
},
{
name: '重量',
units: ['千克', '克', '磅', '盎司'],
factors: [1, 1000, 2.20462, 35.274]
},
{
name: '温度',
units: ['摄氏度', '华氏度', '开尔文'],
factors: [1, 1, 1], // 温度需要特殊处理
isTemperature: true
},
{
name: '面积',
units: ['平方米', '平方厘米', '平方英尺', '公顷'],
factors: [1, 10000, 10.7639, 0.0001]
}
];
// 生命周期:组件创建时初始化计算
aboutToAppear() {
this.calculateResult();
}
build() {
Column({ space: 20 }) {
// 应用标题
Text('单位转换器')
.fontSize(32)
.fontWeight(FontWeight.Bold)
.fontColor('2D3748')
.margin({ top: 20 })
// 分类选择
this.BuildCategorySelector()
// 转换输入区域
this.BuildConverterArea()
// 结果显示
this.BuildResultDisplay()
// 转换信息
this.BuildConversionInfo()
}
.width('100%')
.height('100%')
.padding(20)
.backgroundColor('F7FAFC')
}
// 构建分类选择器 - 演示水平滚动选择
@Builder BuildCategorySelector() {
Scroll() {
Row({ space: 10 }) {
ForEach(this.categories, (category: Category, index: number) => {
Button(category.name)
.onClick(() => {
this.selectedCategory = index;
this.fromUnit = 0;
this.toUnit = 1;
this.calculateResult();
})
.backgroundColor(this.selectedCategory === index ? '4299E1' : 'E2E8F0')
.fontColor(this.selectedCategory === index ? Color.White : '4A5568')
.padding({ left: 16, right: 16 })
.borderRadius(20)
.height(40)
})
}
.padding(10)
}
.scrollable(ScrollDirection.Horizontal)
.width('100%')
.margin({ bottom: 10 })
}
// 构建转换区域 - 演示复杂表单布局
@Builder BuildConverterArea() {
Column({ space: 15 }) {
// 输入行
Row({ space: 10 }) {
// 输入框
TextInput({ placeholder: '输入数值', text: this.inputValue })
.onChange((value: string) => {
// 验证输入是否为有效数字
if (this.isValidNumber(value)) {
this.inputValue = value;
this.calculateResult();
}
})
.type(InputType.Number)
.padding(15)
.backgroundColor(Color.White)
.border({ width: 1, color: 'CBD5E0' })
.borderRadius(8)
.layoutWeight(1)
// 源单位选择
this.BuildUnitPicker(this.fromUnit, false)
}
// 转换方向按钮 - 修复:Button不能直接传入函数
Button('⇅')
.onClick(() => {
// 交换单位
const temp = this.fromUnit;
this.fromUnit = this.toUnit;
this.toUnit = temp;
this.isReversed = !this.isReversed;
this.calculateResult();
})
.backgroundColor('4299E1')
.fontColor(Color.White)
.width(40)
.height(40)
.borderRadius(20)
.margin({ top: 5, bottom: 5 })
// 输出行
Row({ space: 10 }) {
// 结果展示(只读)
TextInput({ text: this.result })
.enabled(false) // 禁用编辑
.padding(15)
.backgroundColor('EDF2F7')
.border({ width: 1, color: 'CBD5E0' })
.borderRadius(8)
.layoutWeight(1)
.fontColor('2D3748')
// 目标单位选择
this.BuildUnitPicker(this.toUnit, true)
}
}
.width('100%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 3, color: '000000', offsetX: 0, offsetY: 1 })
}
// 构建单位选择器 - 修复:使用自定义选择器替代Picker
@Builder BuildUnitPicker(selectedIndex: number, isTarget: boolean) {
Column() {
// 使用Text显示当前选择的单位
Text(this.getCurrentUnitName(selectedIndex))
.fontSize(16)
.fontColor('2D3748')
.padding(10)
.backgroundColor('F7FAFC')
.border({ width: 1, color: 'CBD5E0' })
.borderRadius(8)
.width(120)
.textAlign(TextAlign.Center)
// 单位选择按钮组
Row({ space: 5 }) {
Button('<')
.onClick(() => {
this.selectPreviousUnit(isTarget);
})
.width(25)
.height(25)
.backgroundColor('4299E1')
.fontColor(Color.White)
.fontSize(12)
Button('>')
.onClick(() => {
this.selectNextUnit(isTarget);
})
.width(25)
.height(25)
.backgroundColor('4299E1')
.fontColor(Color.White)
.fontSize(12)
}
.margin({ top: 5 })
}
}
// 构建结果显示 - 演示格式化输出
@Builder BuildResultDisplay() {
// 修复:使用条件渲染而不是逻辑代码
if (this.result && this.inputValue && parseFloat(this.inputValue)) {
Column({ space: 8 }) {
Text('转换结果')
.fontSize(16)
.fontColor('718096')
.alignSelf(ItemAlign.Start)
Text(`${this.inputValue} ${this.getCurrentUnitName(this.fromUnit)} = ${this.result} ${this.getCurrentUnitName(this.toUnit)}`)
.fontSize(20)
.fontWeight(FontWeight.Medium)
.fontColor('2D3748')
.textAlign(TextAlign.Center)
.width('100%')
}
.width('100%')
.padding(15)
.backgroundColor('EBF8FF')
.border({ width: 2, color: '4299E1' })
.borderRadius(8)
}
}
// 构建转换信息 - 修复:移除UI描述中的逻辑代码
@Builder BuildConversionInfo() {
Column({ space: 10 }) {
Text('单位信息')
.fontSize(18)
.fontWeight(FontWeight.Medium)
.fontColor('2D3748')
.alignSelf(ItemAlign.Start)
// 修复:直接调用方法而不是变量声明
Text(this.getConversionInfoText())
.fontSize(14)
.fontColor('4A5568')
.textAlign(TextAlign.Start)
.width('100%')
if (this.categories[this.selectedCategory].isTemperature) {
Text('温度转换使用特殊公式')
.fontSize(12)
.fontColor('718096')
.fontStyle(FontStyle.Italic)
}
}
.width('100%')
.padding(15)
.backgroundColor(Color.White)
.borderRadius(8)
.shadow({ radius: 2, color: '000000', offsetX: 0, offsetY: 1 })
}
// 选择上一个单位
private selectPreviousUnit(isTarget: boolean): void {
const currentCategory = this.categories[this.selectedCategory];
const maxIndex = currentCategory.units.length - 1;
if (isTarget) {
this.toUnit = this.toUnit > 0 ? this.toUnit - 1 : maxIndex;
} else {
this.fromUnit = this.fromUnit > 0 ? this.fromUnit - 1 : maxIndex;
}
this.calculateResult();
}
// 选择下一个单位
private selectNextUnit(isTarget: boolean): void {
const currentCategory = this.categories[this.selectedCategory];
const maxIndex = currentCategory.units.length - 1;
if (isTarget) {
this.toUnit = this.toUnit < maxIndex ? this.toUnit + 1 : 0;
} else {
this.fromUnit = this.fromUnit < maxIndex ? this.fromUnit + 1 : 0;
}
this.calculateResult();
}
// 获取转换信息文本
private getConversionInfoText(): string {
const factor = this.getConversionFactor();
return `1 ${this.getCurrentUnitName(this.fromUnit)} = ${factor.toFixed(6)} ${this.getCurrentUnitName(this.toUnit)}`;
}
// 获取当前单位名称
private getCurrentUnitName(unitIndex: number): string {
return this.categories[this.selectedCategory].units[unitIndex];
}
// 计算转换结果
private calculateResult(): void {
const inputNum = parseFloat(this.inputValue);
if (isNaN(inputNum)) {
this.result = '';
return;
}
const currentCategory = this.categories[this.selectedCategory];
if (currentCategory.isTemperature) {
// 温度转换特殊处理
this.result = this.convertTemperature(inputNum).toFixed(2);
} else {
// 普通单位转换
const factor = this.getConversionFactor();
const calculated = inputNum factor;
// 格式化结果,移除不必要的尾随零
this.result = calculated % 1 === 0 ? calculated.toString() : calculated.toFixed(4);
}
}
// 获取转换系数
private getConversionFactor(): number {
const currentCategory = this.categories[this.selectedCategory];
const fromFactor = currentCategory.factors[this.fromUnit];
const toFactor = currentCategory.factors[this.toUnit];
return fromFactor / toFactor;
}
// 温度转换
private convertTemperature(value: number): number {
const currentCategory = this.categories[this.selectedCategory];
// 先将输入值转换为基准单位(摄氏度)
let celsius: number;
switch (this.fromUnit) {
case 0: // 摄氏度
celsius = value;
break;
case 1: // 华氏度
celsius = (value - 32) 5 / 9;
break;
case 2: // 开尔文
celsius = value - 273.15;
break;
default:
celsius = value;
}
// 再从摄氏度转换为目标单位
switch (this.toUnit) {
case 0: // 摄氏度
return celsius;
case 1: // 华氏度
return celsius 9 / 5 + 32;
case 2: // 开尔文
return celsius + 273.15;
default:
return celsius;
}
}
// 验证数字输入
private isValidNumber(value: string): boolean {
if (value === '' || value === '-') return true;
const num = parseFloat(value);
return !isNaN(num);
}
}
// 分类数据接口
interface Category {
name: string;
units: string[];
factors: number[];
isTemperature?: boolean;
}
想入门鸿蒙开发又怕花冤枉钱?别错过!现在能免费系统学 -- 从 ArkTS 面向对象核心的类和对象、继承多态,到吃透鸿蒙开发关键技能,还能冲刺鸿蒙基础 +高级开发者证书,更惊喜的是考证成功还送好礼!快加入我的鸿蒙班,一起从入门到精通,班级链接:点击免费进入

806

被折叠的 条评论
为什么被折叠?



