代碼功能概述

  1. 一個功能完整的鴻蒙簡易計算器應用,全面展示了ArkTS在用户交互、數學計算、狀態管理和界面佈局等方面的核心能力。主要功能包括:

基本數學運算:支持加、減、乘、除四則運算 

實時計算顯示:實時顯示輸入表達式和計算結果 

連續計算:支持連續運算,自動記憶上一次計算結果 

輸入驗證:防止非法數學表達式,提供錯誤提示 

界面交互:完整的數字鍵盤和操作符按鈕 

清除功能:支持全部清除和逐位清除 

通過這個示例,可以深入理解ArkTS如何實現複雜的用户交互和數學計算邏輯。 

2. 代碼邏輯分析 

應用採用"表達式驅動計算"的架構設計: 

1. 初始化階段:應用啓動時,初始化計算器狀態和顯示內容 

2. 狀態管理:使用多個@State裝飾器管理當前表達式、計算結果和運算狀態 

3. 用户輸入流程: 

   · 數字按鈕 → 追加到當前表達式 → 實時驗證和顯示 

   · 操作符按鈕 → 驗證並追加操作符 → 更新運算狀態 

   · 等號按鈕 → 執行數學計算 → 顯示結果並重置狀態 

   · 清除按鈕 → 重置表達式或逐位刪除 → 恢復初始狀態 

4. 計算邏輯:使用JavaScript的eval()函數執行數學表達式計算 

錯誤處理:捕獲計算異常,顯示友好的錯誤信息

完整代碼

@Entry
@Component
struct CalculatorTutorial {
  @State currentInput: string = '0';
  @State currentExpression: string = '';
  @State result: string = '';
  @State lastOperator: string = '';
  @State isResultShown: boolean = false;
  @State history: string[] = [];

  build() {
    Column({ space: 0 }) {
      // 歷史記錄顯示
      this.BuildHistoryDisplay()
      
      // 顯示區域
      this.BuildDisplay()
      
      // 按鈕區域
      this.BuildButtonGrid()
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#000000')
  }

  @Builder BuildHistoryDisplay() {
    if (this.history.length > 0) {
      Column({ space: 5 }) {
        ForEach(this.history.slice(-3), (item: string) => {
          Text(item)
            .fontSize(14)
            .fontColor('#666666')
            .textAlign(TextAlign.End)
            .width('100%')
            .padding({ right: 20 })
        })
      }
      .width('100%')
      .height(60)
      .justifyContent(FlexAlign.End)
    }
  }

  @Builder BuildDisplay() {
    Column({ space: 5 }) {
      // 表達式顯示
      if (this.currentExpression.length > 0) {
        Text(this.currentExpression)
          .fontSize(20)
          .fontColor('#666666')
          .textAlign(TextAlign.End)
          .width('100%')
          .padding({ right: 20 })
      }
      
      // 結果/輸入顯示
      Text(this.currentInput)
        .fontSize(48)
        .fontWeight(FontWeight.Medium)
        .fontColor('#FFFFFF')
        .textAlign(TextAlign.End)
        .width('100%')
        .padding({ right: 20 })
        .margin({ bottom: 20 })
    }
    .width('100%')
    .height(120)
    .justifyContent(FlexAlign.End)
  }

  @Builder BuildButtonGrid() {
    const buttonLayout = [
      ['C', '±', '%', '÷'],
      ['7', '8', '9', '×'],
      ['4', '5', '6', '-'],
      ['1', '2', '3', '+'],
      ['0', '.', '=', '']
    ];
    
    Column({ space: 12 }) {
      ForEach(buttonLayout, (row: string[]) => {
        Row({ space: 12 }) {
          ForEach(row, (buttonText: string) => {
            if (buttonText) {
              this.BuildCalculatorButton(buttonText)
            }
          })
        }
        .width('100%')
        .justifyContent(FlexAlign.SpaceBetween)
      })
    }
    .width('100%')
    .layoutWeight(1)
    .padding({ left: 12, right: 12, bottom: 20 })
  }

  @Builder BuildCalculatorButton(text: string) {
    const isNumber = !isNaN(Number(text));
    const isOperator = ['÷', '×', '-', '+', '='].includes(text);
    const isFunction = ['C', '±', '%', '.'].includes(text);
    
    let buttonColor = '#333333';
    let textColor = '#FFFFFF';
    
    if (text === 'C') {
      buttonColor = '#A5A5A5';
      textColor = '#000000';
    } else if (isOperator || text === '=') {
      buttonColor = '#FF9500';
    } else if (isFunction) {
      buttonColor = '#A5A5A5';
    }
    
    const buttonWidth = text === '0' ? '48%' : '22%';
    
    Button(text)
      .onClick(() => {
        this.handleButtonPress(text);
      })
      .backgroundColor(buttonColor)
      .fontColor(textColor)
      .fontSize(32)
      .fontWeight(FontWeight.Medium)
      .width(buttonWidth)
      .height(80)
      .borderRadius(40)
  }

  private handleButtonPress(buttonText: string): void {
    switch(buttonText) {
      case 'C':
        this.clearAll();
        break;
      case '±':
        this.toggleSign();
        break;
      case '%':
        this.calculatePercentage();
        break;
      case '.':
        this.addDecimalPoint();
        break;
      case '=':
        this.calculateResult();
        break;
      case '÷':
      case '×':
      case '-':
      case '+':
        this.handleOperator(buttonText);
        break;
      default:
        this.handleNumberInput(buttonText);
    }
  }

  private handleNumberInput(number: string): void {
    if (this.isResultShown) {
      this.currentInput = number;
      this.currentExpression = '';
      this.isResultShown = false;
    } else if (this.currentInput === '0') {
      this.currentInput = number;
    } else {
      this.currentInput += number;
    }
  }

  private handleOperator(operator: string): void {
    if (this.isResultShown) {
      this.currentExpression = this.currentInput + ' ' + operator + ' ';
      this.currentInput = '0';
      this.isResultShown = false;
    } else {
      if (this.currentExpression === '') {
        this.currentExpression = this.currentInput + ' ' + operator + ' ';
      } else {
        this.currentExpression += this.currentInput + ' ' + operator + ' ';
      }
      this.currentInput = '0';
    }
    this.lastOperator = operator;
  }

  private calculateResult(): void {
    if (this.currentExpression === '' || this.lastOperator === '') {
      return;
    }
    
    try {
      // 構建完整的表達式
      let fullExpression = this.currentExpression + this.currentInput;
      
      // 替換顯示符號為計算符號
      fullExpression = fullExpression
        .replace(/×/g, '*')
        .replace(/÷/g, '/');
      
      // 執行計算
      const result = eval(fullExpression);
      
      // 格式化結果
      let formattedResult = '';
      if (Number.isInteger(result)) {
        formattedResult = result.toString();
      } else {
        formattedResult = parseFloat(result.toFixed(8)).toString();
        // 移除末尾的零
        formattedResult = formattedResult.replace(/\.?0+$/, '');
      }
      
      // 更新顯示
      this.result = formattedResult;
      this.currentInput = formattedResult;
      
      // 添加到歷史記錄
      const historyEntry = `${this.currentExpression}${this.currentInput} = ${formattedResult}`;
      this.history.push(historyEntry);
      if (this.history.length > 10) {
        this.history.shift();
      }
      
      // 重置狀態
      this.currentExpression = '';
      this.lastOperator = '';
      this.isResultShown = true;
      
    } catch (error) {
      this.currentInput = '錯誤';
      this.currentExpression = '';
      this.lastOperator = '';
      this.isResultShown = false;
    }
  }

  private clearAll(): void {
    this.currentInput = '0';
    this.currentExpression = '';
    this.result = '';
    this.lastOperator = '';
    this.isResultShown = false;
  }

  private toggleSign(): void {
    if (this.currentInput !== '0') {
      if (this.currentInput.startsWith('-')) {
        this.currentInput = this.currentInput.substring(1);
      } else {
        this.currentInput = '-' + this.currentInput;
      }
    }
  }

  private calculatePercentage(): void {
    const value = parseFloat(this.currentInput);
    if (!isNaN(value)) {
      this.currentInput = (value / 100).toString();
    }
  }

  private addDecimalPoint(): void {
    if (this.isResultShown) {
      this.currentInput = '0.';
      this.currentExpression = '';
      this.isResultShown = false;
    } else if (!this.currentInput.includes('.')) {
      this.currentInput += '.';
    }
  }
}

想入門鴻蒙開發又怕花冤枉錢?別錯過!現在能免費系統學 -- 從 ArkTS  面向對象核心的類和對象、繼承多態,到吃透 鴻蒙開發關鍵技能,還能衝刺鴻蒙基礎 +高級開發者證書,更驚喜的是考證成功還送好禮!快加入我的鴻蒙班,一起從入門到精通,班級鏈接: 點擊https://developer.huawei.com/consumer/cn/training/classDetail/b7365031334e4353a9a0fd6785bb0791?type=1?ha_source=hmosclass&ha_sourceId=89000248免費進入