【Android开发笔记】简易计算器 Demo

模拟日常使用的计算器,提供简单的四则运算功能。

效果图【Android开发笔记】简易计算器 Demo_第1张图片

开发过程

UI布局

  • 使用GridLayout进行布局(6行4列)
  • 使用android:id标记UI控件的唯一id,用于通过id调用findViewById(int)获取UI控件进行操作
  • 使用android:tag保存按钮功能的表示,方便使用for循环进行监听处理

数据结构设计

// 当前显示的字符串
private String showString = null;
// 操作字符串
private String operationString = null;
// 用于计算的字符串
private String[] numStrings = new String[2];
  • showString
    • 用于保存当前用户输入的数字
    • setter方法刷新计算器上显示的数字
  • operationString:
    • 用来保存当前的操作符号
  • numStrings:
    • 用来保存需要进行计算的两个数字

计算器基本初始化流程

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 1. 加载主界面布局显示
    setContentView(R.layout.activity_calculator);
    // 2. 设置清除按钮
    setupRemoveBtn();
    // 3. 设置数字按钮
    setupNumBtn();
    // 4. 设置操作按钮
    setupOperstionBtn();
    // 5. 设置"="按钮
    setupEqualBtn();
}

【Android开发笔记】简易计算器 Demo_第2张图片
setShowString方法的刷新方式:

public void setShowString(String showString) {
    this.showString = showString;
    TextView tv = getResultView();
    // 边界处理
    if (showString == "" || showString == null) {
        showString = "0";
    }
    // 展示
    tv.setText(showString);
}

public TextView getResultView() {
    if (resultView == null) {
        resultView = findViewById(R.id.result);
    }
    return resultView;
}

设置清除按钮逻辑

直接将上面提到的数据结构进行重新的初始化,并刷新UI。代码如下:

private void setupRemoveBtn() {
    getRemoveBtn().setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 清除所有 相当于初始化
            numStrings = new String[2];
            operationString = null;
            // 将计算机显示归零
            setShowString(null);
        }
    });
}

public Button getRemoveBtn() {
    if (removeBtn == null) {
        removeBtn = findViewById(R.id.remove);
    }
    return removeBtn;
}

设置操作按钮逻辑

主要思路:

  • 点击操作符按钮的时候,先保存当前显示的数字。
  • 更贴合真实计算器的功能实现
    • 判断是否第一次使用操作符
    • 判断是否更改操作符的功能
private void setupOperstionBtn() {
    // 循环id来进行监听
    int[] btnIds = {
        R.id.btn_add, R.id.btn_subtract, 
        R.id.btn_multiply, R.id.btn_divide
        };
    for (int btnId: btnIds) {
        Button btn = findViewById(btnId);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String tag = (String)v.getTag();
                if (showString != "") {
                    // 有数字
                    if (numStrings[1] != null) {
                        // 需要重新选择运算符
                        numStrings[0] = numStrings[1];
                        numStrings[1] = null;
                        operationString = tag;
                    } else {
                        // 第一次选择运算符
                        numStrings[0] = showString;
                        operationString = tag;
                    }
                }
            }
        });
    }
}

设置数字按钮逻辑

主要思路:

  • 分开数字与小数点的操作
  • 更贴合这是计算器的功能实现
    • 可支持输出.x表示小数
private void setupNumBtn() {
    int[] btnIds = {
        R.id.btn_0, R.id.btn_1, R.id.btn_2,
        R.id.btn_3, R.id.btn_4, R.id.btn_5,
        R.id.btn_6, R.id.btn_7, R.id.btn_8,
        R.id.btn_9, R.id.btn_decimal_point
    };
    for (int btnId: btnIds) {
        Button btn = findViewById(btnId);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String tag = (String)v.getTag();
                // 获取当前数字
                String showStr = (showString == null) ? "" : showString;
                if ((operationString != null && numStrings[1] == null) || 
                    (showString != null && showString.equals("错误"))) {
                    showStr = "";
                }
                if (tag == ".") {
                    if (showStr.contains(".") == false || showStr == "") {
                        // 当前显示的数字没有小数点的情况
                        showStr += tag;
                    }
                    // 已经有小数点局直接忽略
                } else {
                    // 正常的数字添加
                    showStr += tag;
                }
                // 用户已经输入操作符的情况
                if (operationString != null) {
                    // 动态保存当前显示的字符串
                    numStrings[1] = showStr;
                }
                setShowString(showStr);
            }
        });
    }
}

设置"="按钮逻辑

主要思路:

  • 获取两个保存下来的数字进行选择的操作符的运算
  • 使用BigDecimal进行大数加减乘除处理
  • 边界条件判断:除数为0,直接显示“错误”
private void setupEqualBtn() {
    findViewById(R.id.btn_equal).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (operationString != null && numStrings[0] != null && showString != "") {
                if (numStrings[0] == null || numStrings[1] == null) {
                    return;
                }
                // 小数点为首位的预处理
                for (int i = 0; i < numStrings.length; ++i) {
                    if (numStrings[i].startsWith(".")) {
                        numStrings[i] = 0 + numStrings[i];
                    }
                }
                // 有两个数字和一个操作符的情况 需要计算
                BigDecimal one = new BigDecimal(numStrings[0]);
                BigDecimal two = new BigDecimal(numStrings[1]);
                BigDecimal ans = new BigDecimal("0");
                // 如果除数是 0 显示错误
                if (showString.equals("0") && operationString.equals("/")) {
                    // 重新初始化
                    numStrings = new String[2];
                    operationString = null;
                    showString = null;
                    setShowString("错误");
                    return;
                }
                switch (operationString) {
                    case "+":
                        ans = one.add(two);
                        break;
                    case "-":
                        ans = one.subtract(two);
                            break;
                    case "*":
                        ans = one.multiply(two);
                        break;
                    case "/":
                        ans = one.divide(two);
                        break;
                    default:
                        break;
                }
                String answerString = ans.toString();
                // 消除 12.310后面的0
                answerString = fixNumString(answerString);
                setShowString(answerString);
                // 等于计算完毕后移动数字
                numStrings[0] = numStrings[1];
                numStrings[1] = answerString;
            }
        }
    });
}

细节处理

省略小数后面没有实际意义的0:

private String fixNumString(String str){
    // 默认不是小数不做处理
    if (str.contains(".") == false) { return str; }
    // 反转字符串
    String reverseString = reverseString(str);
    boolean flag = false;
    String result = "";
    for (char ch: reverseString.toCharArray()) {
        // 不要没用的 0 和 .
        if (flag == false && (ch == '0' || ch == '.')) {
            continue;
        }
        if (ch >= '1' && ch <= '9') {
            flag = true;
        }
        result += ch;
    }
    // 转回来
    return reverseString(result);
}

private String reverseString(String str) {
    // 用栈先进后出的特点进行处理
    Stack chStack = new Stack<>();
    char[] strs = str.toCharArray();
    for (char ch: strs) {
        chStack.push(ch);
    }
    String result = "";
    while (chStack.isEmpty() == false) {
        result += chStack.pop();
    }
    return result;
}

你可能感兴趣的:(Android)