"成功不是将来才有的,而是从决定去做的那一刻起,持续累积而成。”
—— 保罗·柯艾略(Paulo Coelho)
前言
学习完成本次实例需要运用的知识:
- 栈的基本操作,将中缀表达式变成后缀表达式并计算结果
- 首选项数据存储的应用,将上次程序留下的表达式进行保存
- ArkUI的基础布局知识,用于布局数字和符号的按钮,以及表达式字体的大小。
本实例需要对上述知识有一定的了解,接下来是代码的实现目标:
- 通过按钮输入表达式,点击等于能够计算出结果,其中,当操作表达式的时候表达式字体较大,点击等于显示结果的时候字体较大,另外可以继续操作结果。
- 首选项数据存储的应用,将上次程序留下的表达式进行保存。
- 识别括号和‘-’号,优先计算括号里的内容,能够进行加减乘除的运算。
- 实现清零和‘<’的功能。
注:本篇文章用于个人学习总结
代码实现
根据以上功能可以将代码分为两大块,第一模块就是实现布局并且能将表达式正确输入上去,第二模块就是处理表达式并计算出结果。
布局
按钮部分
按钮大体分为两种,一种是按下之后把自己的值附上去的,比如数字和加减乘除括号,另一种是按下去之后可以实现某种功能的,比如说等于号,清理以及删除。
按照上述功能我们可以将其封装成如下类:
export default class PressKeysBean {
flag: number;
value: string;
ability?:number
constructor(flag: number, value: string,ability?:number) {
this.flag = flag;
this.value = value;
this.ability=ability
}
}
flag用来区分是否为功能键,而value用来存放值,ability就是功能键的功能加以区分。
import PressKeysBean from './PressKeysItem'
class PressKeysBeanViewModel{
public getPressKeys():Array<Array<PressKeysBean>>{
return [
[
new PressKeysBean(1,'C',0),
new PressKeysBean(0,'7'),
new PressKeysBean(0,'4'),
new PressKeysBean(0,'1'),
new PressKeysBean(1,'<',1)
],
[
new PressKeysBean(1,'('),
new PressKeysBean(0,'8'),
new PressKeysBean(0,'5'),
new PressKeysBean(0,'2'),
new PressKeysBean(0,'0')
],
[
new PressKeysBean(1,')'),
new PressKeysBean(0,'9'),
new PressKeysBean(0,'6'),
new PressKeysBean(0,'3'),
new PressKeysBean(0,'.')
],
[
new PressKeysBean(1,'÷'),
new PressKeysBean(1,'×'),
new PressKeysBean(1,'-'),
new PressKeysBean(1,'+'),
new PressKeysBean(2,'=')
]
]
}
}
let keysModel = new PressKeysBeanViewModel();
export default keysModel as PressKeysBeanViewModel;
至此,我们的十六个键按照功能划分封装好了,接下来就是布局了!
布局可以用Grid布局,也可以用线性布局进行两层循环,这里使用后者。
Row({
space:10}){
ForEach(keysModel.getPressKeys(),(columnItem:Array<PressKeysBean>)=>{
Column({
space:30}){
ForEach(columnItem,(Item:PressKeysBean)=> {
//flag==0,表示是数字键,按下后直接将数字压进栈中
if (Item.flag == 0) {
Button(Item.value).style('#ffffffff','#000000').onClick(()=>{
this.expressions.push(Item.value)
})
//以下是加减乘除键和功能键
} else if (Item.flag == 1) {
Button(Item.value).style('#66ffffff','#000000').onClick(()=>{
//等于0,是清除键,把表达式的值变成空,这里的flag,和flag1初始化。
//flag和flag1是用来控制表达式和字体大小的,可以先不管
if(Item.ability==0){
this.expressions=[]
this.flag=0
this.flag1=0
//这里是删除键,点击一次在栈中弹出一个元素
}else if(Item.ability==1){
this.expressions.pop()
//加减乘除直接赋值
}else {
this.expressions.push(Item.value)
if(this.flag1==1){
this.expressions=[]
this.expressions.push(this.result.toString())
this.expressions.push(Item.value)
this.flag1=0
}
}
})
//这里是等于键,执行的功能是将表达式的结果进行解析赋值出结果
}else if(Item.flag==2){
Button(Item.value).style('#ff20b4cf','#ffffffff').onClick(()=>{
this.result=getCalculate(this.expressions.join(''))
if(Number.isNaN(this.result)){
this.result='表达式有误'
}
this.flag=1
this.flag1=1
})
}
})
}.justifyContent(FlexAlign.SpaceAround)
})
}.justifyContent(FlexAlign.SpaceAround)
.width(350)
.height(310)
.alignItems(VerticalAlign.Bottom)
.margin({
top:280})
表达式和结果部分
情况1:表达式过长
Column({
space:20}){
TextInput({
text:this.expressions.join('')})
.minFontSize(15)
.maxFontSize(this.flag1==1?30:50)
.heightAdaptivePolicy(TextH