Android 小程序:自制简易计算器

My first Android app:计算器 !

在经过了 JavaSE 基础学习后接触 Android 开发基础知识

1周的学习后,我们的培训讲师布置了简易的计算器项目作业(在中期项目中会包含有计算器),这一任务激发了对数字敏感的我强烈兴趣,可是初学者终归是初学者,想一股脑儿得噼里啪啦写出代码实现功能简直是天方夜谭。于是百度了一些计算器逻辑与代码,我以为我看看别人的就能懂,可现实很残酷,我根本看不懂别人的代码!!!可强烈的求知欲与好奇心驱使我:自己来写!!
于是在经历了一周的断断续续研究与“试探”,创建了我第一个独立开发的简易计算器!!!

下文中我会介绍我的开发思路和遇到的 bug 与解决方法,可能在老手的眼中会很愚蠢或是天真,但作为初学者的我…可能是测试到每个深夜的结果。虚心求教各优化步骤,也许我错得很远…

< 开发思路与初步代码 >

(1)类型

在计算器类型上我选择了类似 iphone 手机计算器,原因是:听到项目后第一反应拿起了自己的手机….

Android 小程序:自制简易计算器_第1张图片

(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;

< Bug解决 >

(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 …

你可能感兴趣的:(Android,Project)