在经过了 JavaSE 基础学习后接触 Android 开发基础知识
1周的学习后,我们的培训讲师布置了简易的计算器项目作业(在中期项目中会包含有计算器),这一任务激发了对数字敏感的我强烈兴趣,可是初学者终归是初学者,想一股脑儿得噼里啪啦写出代码实现功能简直是天方夜谭。于是百度了一些计算器逻辑与代码,我以为我看看别人的就能懂,可现实很残酷,我根本看不懂别人的代码!!!可强烈的求知欲与好奇心驱使我:自己来写!!
于是在经历了一周的断断续续研究与“试探”,创建了我第一个独立开发的简易计算器!!!下文中我会介绍我的开发思路和遇到的 bug 与解决方法,可能在老手的眼中会很愚蠢或是天真,但作为初学者的我…可能是测试到每个深夜的结果。虚心求教各优化步骤,也许我错得很远…
(1)类型
在计算器类型上我选择了类似 iphone 手机计算器,原因是:听到项目后第一反应拿起了自己的手机….
(2)变量定义
我的需求是计算数字与数字并显示结果,所以我需要一个随时可以拿出来的输入数据源,以及一个运算后的结果和区分运算符的值。
private TextView text;
private Button btn_e;
private double A = 0.0;
private StringBuffer B = new StringBuffer("");
private int flag = -1;//运算符
private int flagSOS = -1;//临时运算符
private boolean firstRun = true; //判断是否为首次运算
private boolean firstBtn_e = true; //判断小数点是否可以输入
(3)运算逻辑
比如:1+2-3+4-5
这个式子中我认为运算符存在2个主要功能:首先是计算上一轮的结果并显示,然后则是改变运算符以便下一次运算的正确,所以我用
flag 为参数来拿到类型为 double 的结果值。但是它存在一个特殊情况也就是首次运算,所以我们需要对其单独处理。
//这里的参数flag为上一次的运算符
public double ifNum(int flag) {
if (firstRun == true) {
firstRun = false;
if (B.length() == 0) {
return A;
} else {
A = toDouble(B);
return upDouble(A);
}
} else if (B.length() == 0) {
return upDouble(A);
} else if (flag == -1) {
return upDouble(A);
} else if (flag == 0) {
A += toDouble(B);
return upDouble(A);
} else if (flag == 1) {
A -= toDouble(B);
return upDouble(A);
} else if (flag == 2) {
A *= toDouble(B);
return upDouble(A);
} else if (flag == 3) {
A /= toDouble(B);
return upDouble(A);
} else {
return 0;
}
}
同时,我们也需要将全局变量 A 与 B 稍加处理:
//输入值转换为double
public double toDouble(StringBuffer B) {
return Double.valueOf(B.toString());
}
//运算优化A结果
public double upDouble(double A) {
return (double) Math.round(A * 1000000) / 1000000;
}
(4)点击事件
这一部分我觉得是整个项目中最困难也是最复杂的一部,它作为与用户交互的主要区域,这让我久久没有思绪。其中数字键的功能较为简单,只用动态显示我们之前定义的 StringBuffer 值即可,小数点键存在很多需要验证的地方,而运算符键则是最为复杂:它需要 验证/处理/显示 数据。
switch (view.getId()) {
case R.id.n0:
B.append("0");
text.setText(B.toString());
break;
case R.id.n1:
B.append("1");
text.setText(B.toString());
break;
小数点键:
btn_e.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (firstBtn_e == true) { //判断是否可以继续输入小数点
B.append(".");
text.setText(B.toString());
firstBtn_e = false; //不能继续输入小数点了
} else {
Toast.makeText(ToCalculatorActivity.this, "你想输入几个小数点???", Toast.LENGTH_SHORT).show();
}
}
});
运算符键:
case R.id.a:
if (B.length() != 0) {
if (str(B) != 0) { //验证B是否为正确的输入值
break;
}
}
if (B.length() == 0 && firstRun!=true){
flagIsA(); //改变flag为A 也就是0;
break;
}else if (B.length() == 0 && firstRun == true){
text.setText(Double.toString(A));
firstBtn_e = true;
flagIsA();
break;
}
setNum(); //处理数据见下图
flagIsA();
break;
public void setNum() {
text.setText(ifNum(this.flag) + "");
B.setLength(0);
firstBtn_e = true;
}
等于号有时就是那么特殊:
//等于
case R.id.n:
if (B.length() != 0) {
if (str(B) != 0) {
break;
}
}
if(B.length()==0){
text.setText(Double.toString(A));
}else {
text.setText(ifNum(this.flagSOS) + "");
}
firstBtn_e = true;
flag = -1;
break;
(1)输入源空指针异常
在我们需要拿取输入源时加个验证判断的步骤即可:
if(B.length()==0){
text.setText(Double.toString(A));
}else {
text.setText(ifNum(this.flagSOS) + "");
}
(2)小数点前后没有值
同样的,作验证判断,在运算处理前加入:
(这里我很想用正则一了百了,可我不会…)
public int str(StringBuffer b) {
if ('.' == b.charAt(0)) { //首先判断首位是否为小数点
AC();
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setMessage("你是不是来捣乱的??? 数据清空!!! 你重写吧哈哈哈哈")
.setTitle("数据类型异常")
.setIcon(R.drawable.stop)
.create()
.show();
return -1;
} else if ('.' == b.charAt(b.length() - 1)) { //然后判断末位是否为小数点
AC();
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setMessage("你输小数点后面不带数字的啊笨蛋!!! 数据清空!!!,下次看清楚点啊亲!!")
.setTitle("数据类型异常")
.setIcon(R.drawable.stop)
.create()
.show();
return -2;
} else {
return 0;
}
}
(3)多次点击等号崩溃
这个问题困扰了我很久,直接导致了我重写了整个运算逻辑并且优化
我用了1个新的变量 flagSOS 来临时记忆每一次等号前的运算符:
//等于
case R.id.n:
if (B.length() != 0) {
if (str(B) != 0) {
break;
}
}
if(B.length()==0){
text.setText(Double.toString(A));
}else {
text.setText(ifNum(this.flagSOS) + "");
}
firstBtn_e = true;
flag = -1;
break;
至此,程序测试完成,没有崩溃现象,也算是对这一周努力的肯定。
我在想,当我入这行许久后,或者是很多年后,再回头看自己这第一篇博客会不会有其他感触~
现在是凌晨 0 点 43 分,该睡觉了 zzz …