Harmony实战之简易计算器
前言
臭宝们,在学会上一节的基础知识之后,我们来实战一下。
预备知识
我们需要用到的知识点有:
- Column组件
- Row组件
- @Link装饰器
- button组件
- TextInput组件
- @State装饰器
最终效果图
代码实现
index页面(首页)
/**
* @program:
*
* @description:*
*
* @author: 槐月
*
* @create: 2025/4/9-21:11
**/
//import用来引入组件。
import {button_Item}from '../Item/button_Item'
@Entry
@Component
struct Index {//fontTitleSize和fontSubTitleSize是用来控制字体大小的。@State fontTitleSize:number = 35;@State fontSubTitleSize:number = 15;//TitleInput和SubInput是用来控制输入框的。@State TitleInput:string ='0';@State SubInput:string = '';build() {Column(){Column(){TextInput({text:this.TitleInput.toString()}).copyOption(CopyOptions.None).minFontSize(5).maxFontSize(this.fontTitleSize).enabled(false)//禁用输入框.textOverflow(100).textAlign(TextAlign.End).backgroundColor('#75878a')TextInput({text:this.SubInput}).enabled(false).minFontSize(5).maxFontSize(this.fontSubTitleSize).backgroundColor('#75878a').textAlign(TextAlign.End)}.justifyContent(FlexAlign.End).backgroundColor('#75878a').margin({top:20,bottom:140}).padding({right:5}).border({width:2,color:Color.White}).borderRadius(10).height('20%').alignItems(HorizontalAlign.End).width('90%')button_Item({fontTopItem:this.fontTitleSize,fontEndItem:this.fontSubTitleSize,currentInput:this.TitleInput,previousValueString:this.SubInput})}.backgroundColor('#c0c6c9').width('100%').height('100%')}
}
在上面这段代码中,我们使用了Column组件来布局。在Column里面我们又嵌套了一个Column用来放置输入框和按钮。fontTitleSize和fontSubTitleSize是用来控制字体大小的。TitleInput和SubInput是用来控制输入框的。
在Column中内嵌的Column做了以下设置:
- borderRadius(10)是为了让输入框的边框圆角更加明显。
- height(‘20%’)是为了让输入框的高度占整个页面的20%。
- width(‘90%’)是为了让输入框的宽度占整个页面的90%。
- alignItems(HorizontalAlign.End)是为了让输入框的内容向右对齐。
- justifyContent(FlexAlign.End)是为了让输入框的内容向下对齐。
- padding({right:5})是为了让输入框的内容向右偏移。
- margin({top:20,bottom:140})是为了让输入框的内容向下偏移。
- border({width:2,color:Color.White})是为了让输入框的边框更加明显,并且颜色为白色。
- backgroundColor(‘#75878a’)是为了让输入框的背景色为灰色。
- button_Item组件是用来放置按钮的。
- 在button_Item组件中,我们使用了@link装饰器来传递参数。
在textInput组件中,我们使用了@State装饰器来控制输入框的内容。对于textInput组件,我们使用了以下设置:
- textOverflow(100)是为了让输入框的内容超出部分不显示。
- copyOption(CopyOptions.None)是为了禁止复制输入框的内容。
- minFontSize(5)是为了让输入框的最小字体大小为5。
- maxFontSize(this.fontTitleSize)是为了让输入框的最大字体大小为我们定义的变量。
- textAlign(TextAlign.End)是为了让输入框的内容向右对齐。
- backgroundColor(‘#75878a’)是为了让输入框的背景色为灰色。
button_Item组件
import { trustedAppService } from "@kit.DeviceSecurityKit";/**
* @program:
*
* @description:
*
* @author: 槐月
*
* @create: 2025/4/9-21:11
**/
@Extend(Button) function ButtonStatus(){.fontSize(20).width('23%').height('10%').border({width:1,color:Color.Black}).type(ButtonType.Normal).borderRadius(5).margin({top:3,right:3,left:3,bottom:3})
}@Component
export struct button_Item {//字体@Link fontTopItem:number;//字体@Link fontEndItem:number;//内容@Link currentInput:string ;//内容@Link previousValueString:string;//控制@State hasNewNumber :boolean = true;//控制输入@State againInput:boolean = true;//对数据进行操作onClickButton(data:string){switch (data) {case 'C':this.currentInput = '0';this.previousValueString='';this.ConvertFontSize(data)break;case 'DEL':if (this.currentInput.length > 1) {this.currentInput = this.currentInput.slice(0, -1);} else {this.currentInput = '0';}this.ConvertFontSize(data)break;case '=':this.ConvertFontSize(data);this.StringIntoArray();this.againInput = false;break;default:if (this.currentInput.length === 1 && this.currentInput.toString() === "0") {this.currentInput = '';}if (!this.againInput) {this.currentInput = '';this.previousValueString = '';this.againInput = true;}this.currentInput += data;this.ConvertFontSize(data)}}//拆解字符串StringIntoArray(){let charArray = this.currentInput.split("");//结果let result1 = '';let result2 ='';let sum= 0;charArray.forEach((value,index,array)=>{//中缀转后缀try {switch (value){case 'x':for (let i = 0; i < index; i++) {result1+=array[i];}for (let j =index+1 ; j < array.length; j++) {result2+=array[j];}sum = Number(result1)*Number(result2);break;case '/':for (let i = 0; i < index; i++) {result1+=array[i];}for (let j =index+1 ; j < array.length; j++) {result2+=array[j];}sum = Number(result1)/Number(result2);break;case '-':for (let i = 0; i < index; i++) {result1+=array[i];}for (let j =index+1 ; j < array.length; j++) {result2+=array[j];}sum = Number(result1)-Number(result2);break;case '+':for (let i = 0; i < index; i++) {result1+=array[i];}for (let j =index+1 ; j < array.length; j++) {result2+=array[j];}sum = Number(result1)+Number(result2);break;}}catch (e) {}})this.previousValueString = sum.toString();console.info(`${sum}`);}//大小写转换ConvertFontSize(data:string){switch (data){case '=':if(this.hasNewNumber){let Temp = this.fontTopItem;this.fontTopItem = this.fontEndItem;this.fontEndItem = Temp;this.hasNewNumber=false;}break;default :if(!this.hasNewNumber){let Temp = this.fontTopItem;this.fontTopItem = this.fontEndItem;this.fontEndItem = Temp;this.hasNewNumber = true;}}}build() {Column(){Row(){//清除键位Button('C').fontColor('#ee7800').backgroundColor('#75878a').ButtonStatus().onClick(()=>{this.onClickButton('C')})//删除Button('DEL').fontColor(Color.Black).backgroundColor('#75878a').ButtonStatus().onClick(()=>{this.onClickButton('DEL');})Button('/').fontColor(Color.Black).backgroundColor('#75878a').ButtonStatus().onClick(()=>{this.onClickButton('/')// this.currentInput = this.computerResult.toString();})Button('x').fontColor(Color.Black).backgroundColor('#75878a').ButtonStatus().onClick(()=>{this.onClickButton('x')})}.justifyContent(FlexAlign.SpaceAround)Row(){Button('7').fontColor(Color.Black).backgroundColor('#f3f3f3').ButtonStatus().onClick(()=>{this.onClickButton('7')})Button('8').fontColor(Color.Black).backgroundColor('#f3f3f3').ButtonStatus().onClick(()=>{this.onClickButton('8')})Button('9').fontColor(Color.Black).backgroundColor('#f3f3f3').ButtonStatus().onClick(()=>{this.onClickButton('9')})Button('-').fontColor(Color.Black).backgroundColor('#75878a').ButtonStatus().onClick(()=>{this.onClickButton('-')})}.justifyContent(FlexAlign.SpaceAround)Row(){Button('4').fontColor(Color.Black).backgroundColor('#f3f3f3').ButtonStatus().onClick(()=>{this.onClickButton('4')})Button('5').fontColor(Color.Black).backgroundColor('#f3f3f3').ButtonStatus().onClick(()=>{this.onClickButton('5')})Button('6').fontColor(Color.Black).backgroundColor('#f3f3f3').ButtonStatus().onClick(()=>{this.onClickButton('6')})Button('+').backgroundColor('#75878a').fontColor(Color.Black).ButtonStatus().onClick(()=>{this.onClickButton('+')})}.justifyContent(FlexAlign.SpaceAround)Row(){Column(){Row(){Button('1').fontSize(20).border({width:1,color:Color.Black}).fontColor(Color.Black).backgroundColor('#f3f3f3').width('30%').height('10%').type(ButtonType.Normal).borderRadius(5).margin({top:3,right:3,left:3}).onClick(()=>{this.onClickButton('1')})Button('2').fontSize(20).border({width:1,color:Color.Black}).fontColor(Color.Black).backgroundColor('#f3f3f3').width('30%').height('10%').type(ButtonType.Normal).borderRadius(5).margin({top:3,right:3,left:3}).onClick(()=>{this.onClickButton('2')})Button('3').fontSize(20).border({width:1,color:Color.Black}).fontColor(Color.Black).backgroundColor('#f3f3f3').width('30%').height('10%').type(ButtonType.Normal).borderRadius(5).margin({top:3,right:3,left:3}).onClick(()=>{this.onClickButton('3')})}.justifyContent(FlexAlign.SpaceAround)Row(){Button('0').fontSize(20).border({width:1,color:Color.Black}).fontColor(Color.Black).backgroundColor('#f3f3f3').width('63%').height('10%').type(ButtonType.Normal).borderRadius(5).margin({top:3,right:3,left:3}).onClick(()=>{this.onClickButton('0')})Button('.').fontSize(20).border({width:1,color:Color.Black}).fontColor(Color.Black).backgroundColor('#f3f3f3').width('30%').height('10%').type(ButtonType.Normal).borderRadius(5) .margin({top:3,right:3,left:3}).onClick(()=>{this.onClickButton('.')})}}.width('76%')Button('=').fontSize(20).backgroundColor('#ee7800').width('22.5%').height('20%').borderRadius(5).type(ButtonType.Normal).margin({top:3,left:0,right:3}).onClick(()=>{this.onClickButton('=')})}.width('100%')}.width('90%')}
}
在这个代码片段中,我使用了Button()
方法来创建按钮,并为每个按钮设置了不同的样式和事件处理函数。例如,我为数字按钮设置了一个点击事件处理器来更新计算器的输入值,为操作符按钮(如加号、减号等)也设置了相应的事件处理器,并为等号按钮设置了计算结果的事件处理器:
- onClickButton方法用于处理按钮点击事件,根据不同的操作更新计算器的状态。例如,当用户点击数字或运算符时,该方法会被调用以更新当前输入的表达式和显示的结果。
- StringIntoArray方法用于将字符串表达式拆分为数组,以便于后续的计算处理。例如,当用户点击等号时,该方法会被调用以解析输入的数学表达式并计算结果。
- ConvertFontSize方法用于根据屏幕宽度动态调整字体大小,以适应不同设备的显示需求。例如,在计算器界面中,该方法可以根据设备屏幕的尺寸来调整按钮和文本的大小,确保用户在不同大小的屏幕上都能舒适地使用应用。
这样一来,用户就可以通过点击按钮来输入数学表达式并得到计算结果了。例如,当用户在屏幕上依次点击数字7、加号(+
)、数字5和等号(=
)时,应用会显示12的结果。
最终,这段代码实现了基本的计算器功能,用户可以通过点击按钮来输入数学表达式并得到结果。
我已经把源码上传到Gitee仓库了,搜索harmony-os-calculator,即可找到。
臭宝们,快来试试看这个计算器吧!😄