回顾总体目标
计算器界面
上一讲,我们介绍了算法实现流程:
- 主界面代码
public final class MainActivity extends AppCompatActivity implements ResultCallback {
private Calculator calculator;
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.calculator = new Calculator(this);
initListeners();
}
private void initListeners() {
findViewById(R.id.clearBtn).setOnClickListener(view -> calculator.accept(KEY_CLEAR));
findViewById(R.id.addBtn).setOnClickListener(view -> calculator.accept(KEY_ADD));
findViewById(R.id.minusBtn).setOnClickListener(view -> calculator.accept(KEY_MINUS));
findViewById(R.id.multiplyBtn).setOnClickListener(view -> calculator.accept(KEY_MULTIPLY));
findViewById(R.id.divideBtn).setOnClickListener(view -> calculator.accept(KEY_DIV));
findViewById(R.id.getResultBtn).setOnClickListener(view -> calculator.accept(KEY_GET_RESULT));
findViewById(R.id.zeroBtn).setOnClickListener(view -> calculator.accept(KEY_ZERO));
findViewById(R.id.oneBtn).setOnClickListener(view -> calculator.accept(KEY_ONE));
findViewById(R.id.twoBtn).setOnClickListener(view -> calculator.accept(KEY_TWO));
findViewById(R.id.threeBtn).setOnClickListener(view -> calculator.accept(KEY_THREE));
findViewById(R.id.fourBtn).setOnClickListener(view -> calculator.accept(KEY_FOUR));
findViewById(R.id.fiveBtn).setOnClickListener(view -> calculator.accept(KEY_FIVE));
findViewById(R.id.sixBtn).setOnClickListener(view -> calculator.accept(KEY_SIX));
findViewById(R.id.sevenBtn).setOnClickListener(view -> calculator.accept(KEY_SEVEN));
findViewById(R.id.eightBtn).setOnClickListener(view -> calculator.accept(KEY_EIGHT));
findViewById(R.id.nineBtn).setOnClickListener(view -> calculator.accept(KEY_NINE));
findViewById(R.id.dotBtn).setOnClickListener(view -> calculator.accept(KEY_DOT));
}
public void updateResult(@NotNull String text) {
((TextView) findViewById(R.id.resultTv)).setText(text);
}
}
代码简析:
this.calculator = new Calculator(this);
初始化一个Calculator对象,具体的计算逻辑由这个类完成。initListeners
这个方法用来给所有的按钮添加点击事件,全部调用calculator的accept方法,都交出去处理。updateResult
这个方法用来更新计算结果显示。
- 核心计算类:
public final class Calculator {
public static final String KEY_CLEAR = "C";
public static final String KEY_DIV = "÷";
public static final String KEY_MULTIPLY = "×";
public static final String KEY_SEVEN = "7";
public static final String KEY_EIGHT = "8";
public static final String KEY_NINE = "9";
public static final String KEY_MINUS = "-";
public static final String KEY_FOUR = "4";
public static final String KEY_FIVE = "5";
public static final String KEY_SIX = "6";
public static final String KEY_ADD = "+";
public static final String KEY_ONE = "1";
public static final String KEY_TWO = "2";
public static final String KEY_THREE = "3";
public static final String KEY_GET_RESULT = "=";
public static final String KEY_ZERO = "0";
public static final String KEY_DOT = ".";
private final StringBuffer inputStringBuffer= new StringBuffer();;
private final ResultCallback resultCallback;
private static final int CALC_SCALE = 10;
public Calculator(ResultCallback resultCallback) {
this.resultCallback = resultCallback;
}
public final void accept(String input) {
String result = "";
if (KEY_CLEAR.equals(input)) {
clear();
} else if (KEY_ADD.equals(input) || KEY_MINUS.equals(input) || KEY_MULTIPLY.equals(input) || KEY_DIV.equals(input)) {
checkInputOp(input);
} else if (KEY_DOT.equals(input)) {
checkInputDot(input);
} else if (KEY_GET_RESULT.equals(input)) {
result = getResult();
} else {
append(input);
}
if (!result.isEmpty()) {
inputStringBuffer.replace(0, this.inputStringBuffer.length(), result);
}
this.resultCallback.updateResult(this.inputStringBuffer.toString());
}
private String getResult() {
String inputString = inputStringBuffer.toString();
if (inputString.isEmpty())
return "";
List numOrOpList = spitIntoList(inputString);
if (isOp(numOrOpList.get(numOrOpList.size() - 1)))
numOrOpList.remove(numOrOpList.size() - 1);
String result = String.valueOf(calculate(numOrOpList));
result = formatResult(result);
return result;
}
private String formatResult(String result) {
if (result.endsWith(".0"))
result = result.substring(0, result.length() - ".0".length());
return result;
}
private double calculate(List numOrOpList) {
if (numOrOpList.size() == 1) {
return Double.parseDouble(numOrOpList.get(0));
}
int opIndex = numOrOpList.indexOf(KEY_MULTIPLY);
if (opIndex != -1) {
String lastNum = numOrOpList.get(opIndex - 1);
String nextNum = numOrOpList.get(opIndex + 1);
BigDecimal result = new BigDecimal(lastNum).multiply(new BigDecimal(nextNum));
List newList = replaceThreeElementsByOne(numOrOpList, opIndex, result.toString());
return calculate(newList);
}
opIndex = numOrOpList.indexOf(KEY_DIV);
if (opIndex != -1) {
String lastNum = numOrOpList.get(opIndex - 1);
String nextNum = numOrOpList.get(opIndex + 1);
BigDecimal result = new BigDecimal(lastNum).divide(new BigDecimal(nextNum), CALC_SCALE, BigDecimal.ROUND_HALF_EVEN);
List newList = replaceThreeElementsByOne(numOrOpList, opIndex, result.toString());
return calculate(newList);
}
opIndex = numOrOpList.indexOf(KEY_ADD);
if (opIndex != -1) {
String lastNum = numOrOpList.get(opIndex - 1);
String nextNum = numOrOpList.get(opIndex + 1);
BigDecimal result = new BigDecimal(lastNum).add(new BigDecimal(nextNum));
List newList = replaceThreeElementsByOne(numOrOpList, opIndex, result.toString());
return calculate(newList);
}
opIndex = numOrOpList.indexOf(KEY_MINUS);
if (opIndex != -1) {
String lastNum = numOrOpList.get(opIndex - 1);
String nextNum = numOrOpList.get(opIndex + 1);
BigDecimal result = new BigDecimal(lastNum).subtract(new BigDecimal(nextNum));
List newList = replaceThreeElementsByOne(numOrOpList, opIndex, result.toString());
return calculate(newList);
}
return 0.0D;
}
private List spitIntoList(String inputString) {
List list = new ArrayList();
int startIndex = 0;
for (int index = 0; index 0) {
result = inputStringBuffer.charAt(inputStringBuffer.length() - 1) + "";
}
return result;
}
private void append(String input) {
inputStringBuffer.append(input);
}
private void clear() {
inputStringBuffer.delete(0, inputStringBuffer.length());
}
private boolean isDigit(String input) {
return input.compareTo(KEY_ZERO) >= 0 && input.compareTo(KEY_NINE) 0) {
return arr[arr.length - 1];
} else {
return "";
}
}
}
代码简析:
- 2到18行,定义所有的按钮值,用于区分出当前用户按下了什么按钮。
- 20行,定义一个StringBuffer对象,用来记录所有按钮对应值,用户按下1,这个变量内容就变成“1”;又按下+,内容就变成“1+”;再按下“2”,内容就变成“1+2”。
- 21行,用来定义一个接口回调,用于传递计算结果给主界面进行显示。
- 23行,计算过程中会使用到,表明是10进制计算。
- 26行,用来接收接口回调参数。
- 29行,本行定义一个函数,用于处理所有的按键事件。
- 31、32行,如果按下的清除键(C),那就调用调用clear函数(后面具体介绍)。
- 33、34行,处理按键“加减乘除”。
- 35、36行,处理按键“.”。
- 37、38行,处理按键“=”。
- 40行,处理数字。
- 42、44行,如果计算出结果了,就替换inputStringBuffer内容,作为后续计算的起始值。
- 45行,调用回调接口显示当前应该显示的内容,可能是计算过程,如“12+34”,也可能是计算结果,如“46”。
https://gitee.com/hspbc/simple-calculator/tree/master/calculator-android-java