HarmonyOS 应用开发基础案例(二):应用 ArkTS 完成五个算法题

28 阅读4分钟

本案例应用前面学习的基础知识,重点应用ArkTS来实现5个算法题。

1. 案例运用到的知识点

  • ArkTS语言:HarmonyOS应用开发的优选开发语言
  • 自定义组件:由开发者定义的组件
  • 基础自定义弹出框:CustomDialog
  • 文本输入组件:TextInput
  • 其他内置组件:Column/Text/Button
  • 常量与资源分类的访问
  • DevEco Studio的基本使用

1.1. 代码结构

├──entry/src/main/ets/
│  ├──common
│  │  ├──constants
│  │  │  └──Constants.ets                       // 常量类
│  │  └──utils
│  │     ├──CommonUtils.ets                     // 弹窗工具类
│  │     ├──Logger.ets                          // 日志工具类
│  │     └──Method.ets                          // 算法工具类
│  ├──entryability
│  │  └──EntryAbility.ets  
│  ├──entrybackupability
│  │  └──EntryBackupAbility.ets
│  ├──pages
│  │  └──Index.ets                              // 界面实现
│  └──view
│     ├──DaffodilsNumberCustomDialog.ets        // 水仙花数弹窗实现
│     ├──IsLeapYearCustomDialog.ets             // 闰年判断数弹窗实现 
│     ├──IsPalindromicStringCustomDialog.ets    // 回文字符串判断数弹窗实现
│     ├──MultiplicationTableCustomDialog.ets    // 九九乘法表弹窗实现
│     └──StringReversalCustomDialog.ets         // 字符串反转弹窗实现 
└───entry/src/main/resources                    // 应用资源目录

1.1.1. 公共文件与资源

本案例涉及到的常量类和工具类代码如下:

  1. 通用日志类
  • entry/src/main/ets/common/utils/Logger.ets
  1. 常量类
  • entry/src/main/ets/common/constants/Constants.ets

本案例涉及到的资源文件如下:

  1. string.json
  • entry/src/main/resources/base/element/string.json
  1. float.json
  • entry/src/main/resources/base/element/float.json

资源的具体内容及其他相关文件,请参考随书配套源码。

1.2. 首页布局

首先进行首页的UI搭建,效果如图23所示。

// entry/src/main/ets/pages/Index.ets
import { CommonConstants } from '../common/constants/Constants'

@Entry
@Component
struct Index {
  build() {
    Column() {
      Text($r('app.string.ArkTS_Development_Case'))
        .width(CommonConstants.PERCENT_NINETY)
        .margin({
          top: $r('app.float.text_margin_top'),
          bottom: $r('app.float.text_margin_bottom'),
          left: $r('app.float.text_margin_left'),
          right: $r('app.float.text_margin_right')
        })
        .font({
          size: $r('app.float.text_font_size'),
          weight: CommonConstants.FONT_WEIGHT_SEVEN_HUNDRED
        })

      Column() {
        Button($r('app.string.DaffodilsNumber'))
          .width($r('app.float.button_width'))
          .height($r('app.float.button_height'))

        Button($r('app.string.MultiplicationTable'))
          .width($r('app.float.button_width'))
          .height($r('app.float.button_height'))
          .margin({ top: $r('app.float.button_margin_top') })

        Button($r('app.string.IsPalindromicString'))
          .width($r('app.float.button_width'))
          .height($r('app.float.button_height'))
          .margin({ top: $r('app.float.button_margin_top') })

        Button($r('app.string.StringReversal'))
          .width($r('app.float.button_width'))
          .height($r('app.float.button_height'))
          .margin({ top: $r('app.float.button_margin_top') })

        Button($r('app.string.IsLeapYear'))
          .width($r('app.float.button_width'))
          .height($r('app.float.button_height'))
          .margin({
            top: $r('app.float.button_margin_top'),
            bottom: $r('app.float.button_margin_bottom')
          })
      }
    }
    .justifyContent(FlexAlign.SpaceBetween)
    .width(CommonConstants.PERCENT_FULL)
    .height(CommonConstants.PERCENT_FULL)
  }
}

图23 首页效果图

1.3. 水仙花数

水仙花数的概念如图24所示。

图24 水仙花数概念

1.3.1. 水仙花数算法实现

// entry/src/main/ets/common/utils/Method.ets
export function daffodilsNumber(): number[] {
  let result: number[] = []
  for (let i = 100; i < 1000; i++) {
    let unitsDigit: number = i % 10
    let tenthsDigit: number = Math.floor(i / 10) - Math.floor(i / 100) * 10
    let hundredthsDigit: number = Math.floor(i / 100)
    if (i == unitsDigit * unitsDigit * unitsDigit 
        + tenthsDigit * tenthsDigit * tenthsDigit +
      hundredthsDigit * hundredthsDigit * hundredthsDigit) {
      result.push(i)
    }
  }
  return result
}

1.3.2. 水仙花数自定义弹窗

// entry/src/main/ets/views/DaffodilsNumberCustomDialog.ets
import { CommonConstants } from "../common/constants/Constants"
import { daffodilsNumber } from '../common/utils/Method'

@CustomDialog
export struct DaffodilsNumberCustomDialog {
  controller?: CustomDialogController

  build() {
    Column() {
      Column() {
        Text($r('app.string.ArkTS_Development_Case'))
          .height($r('app.float.button_height'))
          .font({size: $r('sys.float.ohos_id_text_size_headline8')})
          .fontColor($r('sys.color.ohos_id_color_text_primary'))
          .margin({top: $r('app.float.dialog_text_margin_top')})
        Text($r('app.string.DaffodilsNumberTitle'))
          .font({size: $r('sys.float.ohos_id_text_size_body2')})
          .fontColor($r('sys.color.ohos_id_color_text_secondary'))
          .margin({left: $r('app.float.dialog_text_margin_left')})
      }
      .alignItems(HorizontalAlign.Center)
      .width(CommonConstants.PERCENT_FULL)
      .height($r('app.float.dialog_text_height'))

      Text(daffodilsNumber().toString())
        .font({size: $r('sys.float.ohos_id_text_size_body1')})
        .fontColor($r('sys.color.ohos_id_color_text_primary'))
        .margin({top: $r('app.float.dialog_padding')})
    }
    .alignItems(HorizontalAlign.Center)
    .padding({
      left: $r('app.float.dialog_padding'),
      right: $r('app.float.dialog_padding'),
      bottom: $r('app.float.dialog_padding')
    })
  }
}

1.3.3. 水仙花数弹窗首页引入

// entry/src/main/ets/pages/Index.ets
// ...

// 引入水仙花弹窗模块
import { 
  DaffodilsNumberCustomDialog
} from '../views/DaffodilsNumberCustomDialog'

@Entry
@Component
struct Index {
  // 定义水仙花弹窗控制器
  daffodilsNumberCustomDialogController: CustomDialogController 
    = new CustomDialogController({
      builder: DaffodilsNumberCustomDialog(),
      alignment: DialogAlignment.Center,
      offset: {
        dx: CommonConstants.OFFSET_X,
        dy: CommonConstants.OFFSET_Y
      }
    })

  build() {
    Column() {
      // ...
      Column() {
        Button($r('app.string.DaffodilsNumber'))
          // ...
          // 打开水仙花弹
          .onClick(() => {
            this.daffodilsNumberCustomDialogController.open()
          })
        // ...
      }
    }
    // ...
  }
}

1.4. 九九乘法表

1.4.1. 打印效果

在日志控制台打印的九九乘法表如图25所示。

图25 效果图

1.4.2. 九九乘法表算法实现

// entry/src/main/ets/common/utils/Method.ets
export function multiplicationTable(): string[][] {
  let result: string[][] = []
  for (let i = 1; i <= 9; i++) {
    let index: string[] = []
    for (let j = 1; j <= i; j++) {
      let temp: string = `${j}${i} = ${i * j}`
      index.push(temp)
    }
    result.push(index)
  }
  return result
}

1.4.3. 九九乘法表自定义弹窗

// entry/src/main/ets/views/MultiplicationTableCustomDialog.ets
import { CommonConstants } from '../common/constants/Constants'

@CustomDialog
export struct MultiplicationTableCustomDialog {
  controller?: CustomDialogController

  build() {
    Column() {
      Column() {
        Text($r('app.string.ArkTS_Development_Case'))
          .height($r('app.float.button_height'))
          .font({ size: $r('sys.float.ohos_id_text_size_headline8') })
          .fontColor($r('sys.color.ohos_id_color_text_primary'))
          .margin({ top: $r('app.float.dialog_text_margin_top') })
        Text($r('app.string.Multiplication_Table_Title'))
          .font({ size: $r('sys.float.ohos_id_text_size_body2') })
          .fontColor($r('sys.color.ohos_id_color_text_secondary'))
          .margin({ left: $r('app.float.dialog_text_margin_left') })
      }
      .alignItems(HorizontalAlign.Center)
      .width(CommonConstants.PERCENT_FULL)
      .height($r('app.float.dialog_text_height'))

      Text($r('app.string.check_info_in_log'))
        .font({ size: $r('sys.float.ohos_id_text_size_body1') })
        .fontColor($r('sys.color.ohos_id_color_text_primary'))
        .margin({ top: $r('app.float.dialog_padding') })
    }
    .alignItems(HorizontalAlign.Center)
    .padding({
      left: $r('app.float.dialog_padding'),
      right: $r('app.float.dialog_padding'),
      bottom: $r('app.float.dialog_padding')
    })
  }
}

1.4.4. 九九乘法表弹窗首页引入

// entry/src/main/ets/pages/Index.ets
// ...
// 引入九九乘法表弹窗、算法函数及日志类模块
import { 
  MultiplicationTableCustomDialog
} from '../views/MultiplicationTableCustomDialog'
import { multiplicationTable } from '../common/utils/Method'
import Logger from '../common/utils/Logger'

@Entry
@Component
struct Index {
  // ...
  
  // 定义九九乘法表弹窗控制器
  multiplicationTableCustomDialogController: CustomDialogController 
    = new CustomDialogController({
      builder: MultiplicationTableCustomDialog(),
      alignment: DialogAlignment.Center,
      offset: {
        dx: CommonConstants.OFFSET_X,
        dy: CommonConstants.OFFSET_Y
      }
    })

  build() {
    Column() {
      //...
      Column() {
        //...
        Button($r('app.string.MultiplicationTable'))
          // ...
          // 打开九九乘法表弹窗,并在日志控制台打印乘法表
          .onClick(() => {
            this.multiplicationTableCustomDialogController.open()
            let result = multiplicationTable()
            for(let index = 0; index < result.length; index++) {
              Logger.info(result[index].toString(), '')
            }
          })

        // ...
      }
    }
    // ...
  }
}

1.5. 回文字符串判断

1.5.1. 交互效果

回文字符串判断演示效果如图26所示。

图26 效果图

1.5.2. 判断回文算法实现

回文字符串概念如图27所示。

图27 回文字符串概念

// entry/src/main/ets/common/utils/Method.ets
export function isPalindromicString(content: string): boolean {
  let result: boolean = true
  let i: number = 0
  let j: number = content.length - 1
  while (i <= j) {
    if (content.charAt(i) != content.charAt(j)) {
      result = false
      break
    }
    i++
    j--
  }
  return result
}

1.5.3. 判断回文自定义弹窗

  • 弹窗组件
// entry/src/main/ets/views/IsPalindromicStringCustomDialog.ets
import { CommonConstants } from "../common/constants/Constants"
import { isPalindromicString } from '../common/utils/Method'
import CommonUtils from '../common/utils/CommonUtils'

@CustomDialog
export struct IsPalindromicStringCustomDialog {
  @State content: string = ''
  @State result: boolean = false
  controller?: CustomDialogController

  build() {
    Column() {
      Column() {
        Text($r('app.string.ArkTS_Development_Case'))
          .height($r('app.float.button_height'))
          .font({ size: $r('sys.float.ohos_id_text_size_headline8') })
          .fontColor($r('sys.color.ohos_id_color_text_primary'))
          .margin({ top: $r('app.float.dialog_text_margin_top') })
        Text($r('app.string.IsPalindromicString'))
          .font({ size: $r('sys.float.ohos_id_text_size_body2') })
          .fontColor($r('sys.color.ohos_id_color_text_secondary'))
          .margin({ left: $r('app.float.dialog_text_margin_left') })
      }
      .alignItems(HorizontalAlign.Center)
      .width(CommonConstants.PERCENT_FULL)
      .height($r('app.float.dialog_text_height'))

      TextInput({ placeholder: CommonConstants.STRING_INPUT })
        .margin({ top: $r('app.float.dialog_padding')})
        .height($r('app.float.dialog_textInput_height'))
        .showUnderline(true)
        .onChange((value: string) => {
          this.content = value
        })

      Button($r('app.string.IsPalindromicString'))
        .width($r('app.float.dialog_button_width'))
        .margin({
          top: $r('app.float.button_margin_bottom'),
          bottom: $r('app.float.dialog_padding')
        })
        .onClick(() => {
          this.result = isPalindromicString(this.content)
          if (this.result) {
            CommonUtils.showToast(CommonConstants.PALINDROMIC_STRING_YES)
          } else {
            CommonUtils.showToast(CommonConstants.PALINDROMIC_STRING_NO)
          }
        })
    }
    .alignItems(HorizontalAlign.Center)
    .padding({
      left: $r('app.float.dialog_padding'),
      right: $r('app.float.dialog_padding')
    })
  }
}
  • 轻提示弹框类封装
// entry/src/main/ets/common/utils/CommonUtils.ets
import { promptAction } from '@kit.ArkUI'
import { CommonConstants } from '../constants/Constants'

export class CommonUtils {
  showToast(message: string) {
    promptAction.showToast({
      message: message,
      duration: CommonConstants.TOAST_TIME
    })
  }
}

let commonUtils = new CommonUtils()

export default commonUtils

1.5.4. 判断回文弹窗首页引入

// entry/src/main/ets/pages/Index.ets
// ...
// 引入判断回文弹窗
import { 
  IsPalindromicStringCustomDialog
} from '../views/IsPalindromicStringCustomDialog'

@Entry
@Component
struct Index {
  //...
  // 定义判断回文弹窗控制器
  isPalindromicStringCustomDialogController: CustomDialogController 
    = new CustomDialogController({
      builder: IsPalindromicStringCustomDialog(),
      alignment: DialogAlignment.Center,
      offset: {
        dx: CommonConstants.OFFSET_X,
        dy: CommonConstants.OFFSET_Y
      }
    })

  build() {
    Column() {
      // ...
      Column() {
        // ...
        Button($r('app.string.IsPalindromicString'))
          // ...
          // 打开判断回文弹窗
          .onClick(() => {
            this.isPalindromicStringCustomDialogController.open()
          })
        //...
      }
    }
    // ...
  }
}

1.6. 字符串反转

1.6.1. 交互效果

字符串反转的交互效果如图28所示。

图28 效果图

1.6.2. 字符串反转算法实现

// entry/src/main/ets/common/utils/Method.ets
export function stringReversal(content: string): string {
  let result: string = ''
  for (let index = content.length - 1; index >= 0; index--) {
    result += content.charAt(index)
  }
  return result
}

1.6.3. 字符串反转自定义窗口

// entry/src/main/ets/views/StringReversalCustomDialog.ets
import { CommonConstants } from '../common/constants/Constants'
import CommonUtils from '../common/utils/CommonUtils'
import { stringReversal } from '../common/utils/Method'

@CustomDialog
export struct StringReversalCustomDialog {
  @State content: string = '';
  @State result: string = '';
  controller?: CustomDialogController;

  build() {
    Column() {
      Column() {
        Text($r('app.string.ArkTS_Development_Case'))
          .height($r('app.float.button_height'))
          .font({ size: $r('sys.float.ohos_id_text_size_headline8') })
          .fontColor($r('sys.color.ohos_id_color_text_primary'))
          .margin({ top: $r('app.float.dialog_text_margin_top') })
        Text($r('app.string.StringReversal'))
          .font({ size: $r('sys.float.ohos_id_text_size_body2') })
          .fontColor($r('sys.color.ohos_id_color_text_secondary'))
          .margin({ left: $r('app.float.dialog_text_margin_left') })
      }
      .alignItems(HorizontalAlign.Center)
      .width(CommonConstants.PERCENT_FULL)
      .height($r('app.float.dialog_text_height'))

      TextInput({ placeholder: CommonConstants.STRING_INPUT })
        .margin({ top: $r('app.float.dialog_padding') })
        .height($r('app.float.dialog_textInput_height'))
        .showUnderline(true)
        .onChange((value: string) => {
          this.content = value;
        })
      Button($r('app.string.StringReversal'))
        .width($r('app.float.dialog_button_width'))
        .margin({
          top: $r('app.float.button_margin_bottom'),
          bottom: $r('app.float.dialog_padding')
        })
        .onClick(() => {
          this.result = stringReversal(this.content)
          CommonUtils.showToast(CommonConstants.STRING_PRE + this.result)
        })
    }
    .alignItems(HorizontalAlign.Center)
    .padding({
      left: $r('app.float.dialog_padding'),
      right: $r('app.float.dialog_padding')
    })
  }
}

1.6.4. 字符串反转弹窗首页引入

// entry/src/main/ets/pages/Index.ets
// ...
// 引入字符串反转弹窗
import { StringReversalCustomDialog } from '../views/StringReversalCustomDialog'

@Entry
@Component
struct Index {
  // ...
  // 定义字符串反转弹窗控制器
  stringReversalCustomDialogController: CustomDialogController 
    = new CustomDialogController({
      builder: StringReversalCustomDialog(),
      alignment: DialogAlignment.Center,
      offset: {
        dx: CommonConstants.OFFSET_X,
        dy: CommonConstants.OFFSET_Y
      }
    })
  
  build() {
    Column() {
      Text($r('app.string.ArkTS_Development_Case'))
        .width(CommonConstants.PERCENT_NINETY)
        .margin({
          top: $r('app.float.text_margin_top'),
          bottom: $r('app.float.text_margin_bottom'),
          left: $r('app.float.text_margin_left'),
          right: $r('app.float.text_margin_right')
        })
        .font({
          size: $r('app.float.text_font_size'),
          weight: CommonConstants.FONT_WEIGHT_SEVEN_HUNDRED
        })

      Column() {
        // ...
        Button($r('app.string.StringReversal'))
          // ...
          // 打开字符串反转弹窗
          .onClick(() => {
            this.stringReversalCustomDialogController.open()
          })
        // ...
      }
    }
    // ...
  }
}

1.7. 闰年判断

1.7.1. 交互效果

闰年判断的交互效果如图29所示。

图29 效果图

1.7.2. 判断闰年算法实现

// entry/src/main/ets/common/utils/Method.ets
export function isLeapYear(year: number): boolean {
  let result: boolean = false;
  if ((year % 4 == 0 && year % 100 != 0) || (year % 400 === 0)) {
    result = true
  } else {
    result = false
  }
  return result
}

1.7.3. 判断闰年自定义弹窗

// entry/src/main/ets/views/IsLeapYearCustomDialog.ets
import { CommonConstants } from '../common/constants/Constants'
import CommonUtils from '../common/utils/CommonUtils'
import { isLeapYear } from '../common/utils/Method'

@CustomDialog
export struct IsLeapYearCustomDialog {
  @State content: string = ''
  @State result: boolean = false
  IsPalindromicStringCustomDialogController?: CustomDialogController

  build() {
    Column() {
      Column() {
        Text($r('app.string.ArkTS_Development_Case'))
          .height($r('app.float.button_height'))
          .font({ size: $r('sys.float.ohos_id_text_size_headline8') })
          .fontColor($r('sys.color.ohos_id_color_text_primary'))
          .margin({ top: $r('app.float.dialog_text_margin_top') })
        Text($r('app.string.Judgment_of_leap_year'))
          .font({ size: $r('sys.float.ohos_id_text_size_body2') })
          .fontColor($r('sys.color.ohos_id_color_text_secondary'))
          .margin({ left: $r('app.float.dialog_text_margin_left') })
      }
      .alignItems(HorizontalAlign.Center)
      .width(CommonConstants.PERCENT_FULL)
      .height($r('app.float.dialog_text_height'))

      TextInput({ placeholder: CommonConstants.LEAP_YEAR_INPUT })
        .margin({ top: $r('app.float.dialog_padding') })
        .height($r('app.float.dialog_textInput_height'))
        .showUnderline(true)
        .onChange((value: string) => {
          this.content = value;
        })
      Button($r('app.string.IsLeapYear'))
        .width($r('app.float.dialog_button_width'))
        .margin({
          top: $r('app.float.button_margin_bottom'),
          bottom: $r('app.float.dialog_padding')
        })
        .onClick(() => {
          this.result = isLeapYear(Number.parseInt(this.content))
          if (this.result) {
            CommonUtils.showToast(CommonConstants.LEAP_YEAR_YES)
          } else {
            CommonUtils.showToast(CommonConstants.LEAP_YEAR_NO)
          }
        })
    }
    .alignItems(HorizontalAlign.Center)
    .padding({
      left: $r('app.float.dialog_padding'),
      right: $r('app.float.dialog_padding')
    })
  }
}

1.7.4. 判断闰年弹窗首页引入

// entry/src/main/ets/pages/Index.ets
// ...
// 引入判断闰年弹窗
import { IsLeapYearCustomDialog } from '../views/IsLeapYearCustomDialog'

@Entry
@Component
struct Index {
  // ...
  // 定义判断闰年弹窗控制器
  isLeapYearCustomDialogController: CustomDialogController 
    = new CustomDialogController({
      builder: IsLeapYearCustomDialog(),
      alignment: DialogAlignment.Center,
      offset: {
        dx: CommonConstants.OFFSET_X,
        dy: CommonConstants.OFFSET_Y
      }
    })

  build() {
    Column() {
      // ...
      Column() {
        // ...
        Button($r('app.string.IsLeapYear'))
          // ...
          // 打开判断闰年弹窗
          .onClick(() => {
            this.isLeapYearCustomDialogController.open()
          })
      }
      // ...
    }
    // ...
  }
}

✋ 需要参加鸿蒙认证的请点击 鸿蒙认证链接

****