鸿蒙UI开发快速入门 —— part11: 鸿蒙计算器开发实践

文章来自公众号“Harmony自习室”

图片

1、前言

经过我们前面10章的学习,我们基本上可以开发出一个简单的APP了,为了巩固学习的内容,我们先开发一个计算器APP来连个手(文末有源代码),界面如下:

图片

  • 包含基本的计算器运算功能

  • 支持一键清空,支持逐个删除数字

  • 支持将上次计算的过程保存下来,下次打开app继续;

  • 支持清理之前保存的记录

这里面我们会用到知识如下:

  1. 开发UI界面(基本控件的使用以及基本布局的使用);

  2. 监听用户点击事件,在输入栏中及时反馈(动态交互);

  3. 支持将过程持久化到本地,下次打开后自动恢复;

let's go!💪🏻💪🏻💪🏻

2、创建项目 & 初始化

打开开发工具 DevEco-Studio,按照以下顺序创建项目,过程不再详述,看截图。

图片

图片

图片

3、UI描述

我们的布局比较简单,分三个大块从上到下,分别是:

  1. 用户输入与计算结果显示部分;

  2. 核心数字键盘部分;

  3. 一个大的=按钮

示意图如下:

图片

我们可以注意到,数字按钮的样式是一样的(蓝色),操作符按钮的样式也是一样的(绿色),三个功能按钮的样式也是一样的(红色),因此,我们可以使用鸿蒙的样式复用只是来减少重复代码量。

我们三部分复用的样式代码如下:

// 数字键盘的公共样式@Extend(Button) function numberBtn(num: number, click: (num: number) => void) {  .type(ButtonType.Capsule)  .width(60)  .height(60)  .onClick(() => click(num))}// 运算符公共样式@Extend(Button) function operatorBtn() {  .type(ButtonType.Capsule)  .backgroundColor(Color.Green)  .width(60)  .height(60)}// 额外功能公共样式@Extend(Button) function extraBtn() {  .type(ButtonType.Capsule)  .width(60)  .height(60)  .backgroundColor(Color.Red)}

紧接着就是我们的UI描述部分代码,如下:

  build() {    Column() {      Column() {        Text(this.message)          .fontSize(20)          .width('100%')          .textAlign(TextAlign.End)      }      .padding(10)      .backgroundColor('gray')      .borderWidth(1)      .borderRadius(10)      .margin(10)      Row() {        Button('7').numberBtn(7, this.onNumberClick)        Button('8').numberBtn(8, this.onNumberClick)        Button('9').numberBtn(9, this.onNumberClick)        Button('重置').extraBtn().onClick(this.onResetClick)      }      .justifyContent(FlexAlign.SpaceAround)      .numberRow()      Row() {        Button('4').numberBtn(4, this.onNumberClick)        Button('5').numberBtn(5, this.onNumberClick)        Button('6').numberBtn(6, this.onNumberClick)        Button('删除').extraBtn().onClick(this.onDeleteClick)      }      .numberRow()      .justifyContent(FlexAlign.SpaceAround)      Row() {        Button('1').numberBtn(1, this.onNumberClick)        Button('2').numberBtn(2, this.onNumberClick)        Button('3').numberBtn(3, this.onNumberClick)        Button('清理').extraBtn().onClick(this.onClearClick)      }      .numberRow()      .justifyContent(FlexAlign.SpaceAround)      Row() {        Button('%')          .type(ButtonType.Capsule)          .width(60)          .height(60)        Button('0').numberBtn(0, this.onNumberClick)        Button('.')          .type(ButtonType.Capsule)          .width(60)          .height(60)          .onClick(this.onDotClick)        Button('保存').operatorBtn().onClick(this.onSaveClick)      }      .numberRow()      .justifyContent(FlexAlign.SpaceAround)      Row() {        Button('x')          .operatorBtn()          .onClick(() => this.onOperatorClick('x'))        Button('÷')          .operatorBtn()          .onClick(() => this.onOperatorClick('÷'))        Button('+')          .operatorBtn()          .onClick(() => this.onOperatorClick('+'))        Button('-')          .operatorBtn()          .onClick(() => this.onOperatorClick('-'))      }      .numberRow()      .justifyContent(FlexAlign.SpaceAround)      Row() {        Button('=')          .width('100%')          .backgroundColor(Color.Pink)          .onClick(this.onCalcClick)      }      .margin(10)    }    .height('100%')  }

4、用户交互

紧接着,我们来实现用户的功能交互

  • 用户点击数字按钮时,监听器事件

  onNumberClick = (num: number) => {    if (this.message === '0') {      this.message = `${num}`;    } else {      this.message += `${num}`    }  }
  • 用户点击运算符按钮时的监听器事件

  onOperatorClick = (_opt: string) => {    this.message += _opt;    this.calcFinished = false;  }
  • 数据持久化和清空持久化数据

  onSaveClick = () => {    AppStorage.SetOrCreate('lastResult', this.message);  }  onClearClick = () => {    PersistentStorage.DeleteProp('lastResult')    this.message = '0';  }

其他的功能感兴趣可以在文末看详细的源代码。演示如下(包含了数据持久化,现场恢复的演示)

图片

5、源代码

代码仓库地址:鸿蒙计算器

速览核心的UI代码:​​​​​​​

// 数字键盘的公共样式@Extend(Button) function numberBtn(num: number, click: (num: number) => void) {  .type(ButtonType.Capsule)  .width(60)  .height(60)  .onClick(() => click(num))}// 运算符公共样式@Extend(Button) function operatorBtn() {  .type(ButtonType.Capsule)  .backgroundColor(Color.Green)  .width(60)  .height(60)}// 额外功能公共样式@Extend(Button) function extraBtn() {  .type(ButtonType.Capsule)  .width(60)  .height(60)  .backgroundColor(Color.Red)}PersistentStorage.PersistProp('lastResult', '0');type Operator = '+' | '-' | '*' | '/' | '(' | ')';// 传入字符串,运算其结果(可以跳过)function calculate(expression: string): number {    //.. 这部分代码是计算用户输入结果d的,不重要,省略}@Entry@Componentstruct Index {  @StorageProp('lastResult') message: string = '0'  calcFinished: boolean = true;  @Styles numberRow() {    .width('100%')    .margin({ bottom: 10 })  }  build() {    Column() {      Column() {        Text(this.message)          .fontSize(20)          .width('100%')          .textAlign(TextAlign.End)      }      .padding(10)      .backgroundColor('gray')      .borderWidth(1)      .borderRadius(10)      .margin(10)      Row() {        Button('7').numberBtn(7, this.onNumberClick)        Button('8').numberBtn(8, this.onNumberClick)        Button('9').numberBtn(9, this.onNumberClick)        Button('重置').extraBtn().onClick(this.onResetClick)      }      .justifyContent(FlexAlign.SpaceAround)      .numberRow()      Row() {        Button('4').numberBtn(4, this.onNumberClick)        Button('5').numberBtn(5, this.onNumberClick)        Button('6').numberBtn(6, this.onNumberClick)        Button('删除').extraBtn().onClick(this.onDeleteClick)      }      .numberRow()      .justifyContent(FlexAlign.SpaceAround)      Row() {        Button('1').numberBtn(1, this.onNumberClick)        Button('2').numberBtn(2, this.onNumberClick)        Button('3').numberBtn(3, this.onNumberClick)        Button('清理').extraBtn().onClick(this.onClearClick)      }      .numberRow()      .justifyContent(FlexAlign.SpaceAround)      Row() {        Button('%')          .type(ButtonType.Capsule)          .width(60)          .height(60)        Button('0').numberBtn(0, this.onNumberClick)        Button('.')          .type(ButtonType.Capsule)          .width(60)          .height(60)          .onClick(this.onDotClick)        Button('保存').operatorBtn().onClick(this.onSaveClick)      }      .numberRow()      .justifyContent(FlexAlign.SpaceAround)      Row() {        Button('x')          .operatorBtn()          .onClick(() => this.onOperatorClick('x'))        Button('÷')          .operatorBtn()          .onClick(() => this.onOperatorClick('÷'))        Button('+')          .operatorBtn()          .onClick(() => this.onOperatorClick('+'))        Button('-')          .operatorBtn()          .onClick(() => this.onOperatorClick('-'))      }      .numberRow()      .justifyContent(FlexAlign.SpaceAround)      Row() {        Button('=')          .width('100%')          .backgroundColor(Color.Pink)          .onClick(this.onCalcClick)      }      .margin(10)    }    .height('100%')  }  resetCheck() {    if (this.calcFinished) {      this.message = '0';      this.calcFinished = false;    }  }  onNumberClick = (num: number) => {    this.resetCheck();    if (this.message === '0') {      this.message = `${num}`;    } else {      this.message += `${num}`    }  }  onOperatorClick = (_opt: string) => {    this.message += _opt;    this.calcFinished = false;  }  onDotClick = () => {    this.resetCheck();    this.message += '.';  }  onResetClick = () => {    this.message = '0';    this.calcFinished = true;  }  onDeleteClick = () => {    this.resetCheck();    if (this.message.length > 1) {      this.message = this.message.substr(0, this.message.length - 1);    } else {      this.message = '0'    }  }  onSaveClick = () => {    AppStorage.SetOrCreate('lastResult', this.message);  }  onClearClick = () => {    PersistentStorage.DeleteProp('lastResult')    this.message = '0';  }  onCalcClick = () => {    this.message = calculate(this.message.replace(/x/g, '*').replace(/÷/g, '/')) + '';    this.calcFinished = true;  }}

6、结语

从代码我们可以看到,依旧存在很多相似的重复代码,我们还可以优化下吗?

答案是可以的,使用条件渲染。

请持续关注 "鸿蒙UI开发快速入门 —— part11"

如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!

扫描下面的二维码关注公众号。

图片

  • 38
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值