> 文档中心 > 简单计算器

简单计算器


效果图:

具体实现

  • 代码结构

 

  • 应用初始化

    计算器应用使用的是自定义的按键,为避免用户在输入数学表达式时,系统自动弹出软键盘,本应用在初始化时,会在入口类MainAbility禁止应用弹出软键盘。

      getWindow().setLayoutFlags(WindowManager.LayoutConfig.MARK_ALT_FOCUSABLE_IM,  WindowManager.LayoutConfig.MARK_ALT_FOCUSABLE_IM);

 随后会在计算器交互界面类MainAbilitySlice中,完成界面渲染和按键点击事件绑定。

@Override public void onStart(Intent intent) {     super.onStart(intent);     super.setUIContent(ResourceTable.Layout_ability_main);      initView();     initListener(); }
  • 主页面布局

     布局文件 ability_main.xml

                                                                                                                                                 
  • 逻辑实现
package com.example.counter_demo.slice;import com.example.counter_demo.utils.MathUtil;import com.example.counter_demo.ResourceTable;import ohos.aafwk.ability.AbilitySlice;import ohos.aafwk.content.Intent;import ohos.agp.components.Component;import ohos.agp.components.Text;import ohos.agp.components.TextField;import java.util.EmptyStackException;import java.util.regex.Pattern;/** * MainAbilitySlice * * @since 2021年8月22日11:55:18 * */public class MainAbilitySlice extends AbilitySlice {    /**     * number component     */    private static int[] numberComponentIds = {ResourceTable.Id_seven, ResourceTable.Id_eight, ResourceTable.Id_nine,     ResourceTable.Id_four, ResourceTable.Id_five, ResourceTable.Id_six, ResourceTable.Id_one,     ResourceTable.Id_two, ResourceTable.Id_three, ResourceTable.Id_zero, ResourceTable.Id_radix_point    };    /**     * operator component     */    private static int[] operatorComponentIds = {ResourceTable.Id_divide, ResourceTable.Id_multiply,     ResourceTable.Id_minus, ResourceTable.Id_divide_remainder, ResourceTable.Id_plus    };    private TextField inputText;    private Text preResult;    @Override    public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); initView(); initListener();    }    private void initView() { if (findComponentById(ResourceTable.Id_input_text) instanceof TextField) {     inputText = (TextField) findComponentById(ResourceTable.Id_input_text);     inputText.requestFocus(); } if (findComponentById(ResourceTable.Id_pre_result) instanceof Text) {     preResult = (Text) findComponentById(ResourceTable.Id_pre_result); }    }    private void initListener() { findComponentById(ResourceTable.Id_number_cancel).setClickedListener(new Component.ClickedListener() {     @Override     public void onClick(Component component) {  preResult.setText("");  inputText.setText("");     } }); findComponentById(ResourceTable.Id_delete).setClickedListener(new Component.ClickedListener() {     @Override     public void onClick(Component component) {  if (inputText.getText().isEmpty()) {      return;  }  inputText.setText(inputText.getText().substring(0, inputText.getText().length() - 1));     } }); findComponentById(ResourceTable.Id_equal_sign).setClickedListener(new Component.ClickedListener() {     @Override     public void onClick(Component component) {  calculateResult(inputText.getText(), false);     } }); for (int componentId : numberComponentIds) {     findComponentById(componentId).setClickedListener(new Component.ClickedListener() {  @Override  public void onClick(Component component) {      bindNumberClickListener(componentId);  }     }); } for (int componentId : operatorComponentIds) {     findComponentById(componentId).setClickedListener(new Component.ClickedListener() {  @Override  public void onClick(Component component) {      bindOperatorClickListener(componentId);  }     }); }    }    private void bindNumberClickListener(int componentId) { String oldValue = inputText.getText(); String inputValue = ""; if (findComponentById(componentId) instanceof Text) {     Text text = (Text) findComponentById(componentId);     inputValue = text.getText(); } if (oldValue.isEmpty() && ".".equals(inputValue)) {     return; } if ("0".equals(oldValue) && !".".equals(inputValue)) {     inputText.setText(inputValue); } else {     inputText.append(inputValue); } calculateResult(inputText.getText(), true);    }    private void bindOperatorClickListener(int componentId) { String oldValue = inputText.getText(); String inputValue = ""; if (findComponentById(componentId) instanceof Text) {     Text text = (Text) findComponentById(componentId);     inputValue = text.getText(); } if (oldValue.isEmpty()) {     inputText.setText(inputValue); } else if (MathUtil.isOperator(oldValue.substring(oldValue.length() - 1))  && MathUtil.isOperator(inputValue)) {     String newValue = oldValue.substring(0, oldValue.length() - 1) + inputValue;     inputText.setText(newValue); } else {     inputText.append(inputValue); } calculateResult(inputText.getText(), true);    }    private void calculateResult(String exp, Boolean isAutoCalculate) { if (exp.isEmpty()) {     return; } // 只有数字 不计算 String pattern = "(\\d*\\.?\\d*)|(0\\.\\d*[1-9])"; boolean isMatch = Pattern.matches(pattern, exp); if (isMatch) {     return; } // 末位是运算符 不计算 if (MathUtil.isOperator(exp.substring(exp.length() - 1))) {     return; } String resultValue; try {     resultValue = MathUtil.getResultString(exp); } catch (NumberFormatException | ArithmeticException | EmptyStackException e) {     preResult.setText("错误");     return; } if (isAutoCalculate) {     preResult.setText(resultValue);     return; } preResult.setText(""); inputText.setText(resultValue);    }    @Override    public void onActive() { super.onActive();    }    @Override    public void onForeground(Intent intent) { super.onForeground(intent);    }}
  • delete删除键处理
    findComponentById(ResourceTable.Id_delete).setClickedListener(new Component.ClickedListener() {     @Override     public void onClick(Component component) {  if (inputText.getText().isEmpty()) {      return;  }  inputText.setText(inputText.getText().substring(0, inputText.getText().length() - 1));     } });

 

 具体 MathUtil 工具类实现

package com.example.counter_demo.utils;import java.math.BigDecimal;import java.util.Stack;/** * MathUtil * * @since 2021年8月22日11:55:02 * 类说明:数学运算工具类 */public class MathUtil {    // 数字栈中分隔数字时使用    private static String separateStr = "@";    // 保留小数位数    private static final int DECIMAL_DIGIT = 6;    // 不包含指定字符    private static final int NOT_CONTAIN = -1;    // 高优先级    private static final int HIGH_PRIORITY = 2;    // 低优先级    private static final int LOW_PRIORITY = 1;    private MathUtil() {    }    public static String getResultString(String exp) { Stack numStack = new Stack(); numStack.push(separateStr); // 数字用@分开,数字栈中@号 为了便于区分小数 Stack oprStack = new Stack(); String[] strings = exp.split(""); for (String singleStr : strings) {     if (isOperator(singleStr)) {  spiltExp(numStack, oprStack, singleStr);     } else {  numStack.push(singleStr);     } } while (!oprStack.isEmpty()) {     combineString(numStack);     compute(numStack, oprStack); } numStack.pop(); String resultValue = numStack.peek(); return resultValue;    }    private static void spiltExp(Stack numStack, Stack oprStack, String singleStr) { // 运算符间的字符拼接成一个数字 combineString(numStack); if (!oprStack.isEmpty()) {     // 先处理优先级高的运算符     while (!oprStack.isEmpty() && priority(singleStr) <= priority(oprStack.peek())) {  combineString(numStack);  compute(numStack, oprStack);     } } oprStack.push(singleStr);    }    private static void compute(Stack numStack, Stack oprStack) { BigDecimal result = null; numStack.pop(); BigDecimal rightNumber = new BigDecimal(numStack.pop()); numStack.pop(); BigDecimal leftNumber = new BigDecimal(numStack.pop()); String operator = oprStack.pop(); switch (operator) {     case "-":  result = leftNumber.subtract(rightNumber);  break;     case "+":  result = leftNumber.add(rightNumber);  break;     case "%":  result = leftNumber.divideAndRemainder(rightNumber)[1];  break;     case "×":  result = leftNumber.multiply(rightNumber);  break;     case "÷":  result = leftNumber.divide(rightNumber, DECIMAL_DIGIT, BigDecimal.ROUND_HALF_UP);  break;     default:  break; } numStack.push(result.stripTrailingZeros().toPlainString()); numStack.push(separateStr);    }    private static void combineString(Stack stack) { if (separateStr.equals(stack.peek())) {     return; } StringBuilder numberBuilder = new StringBuilder(); while (true) {     String string = stack.peek();     if (separateStr.equals(string)) {  break;     }     numberBuilder.insert(0, string);     stack.pop(); } stack.push(numberBuilder.toString()); stack.push(separateStr); numberBuilder.delete(0, numberBuilder.length());    }    /**     * Determines whether a string is an operator.     *     * @param singleStr Character string to be judged     * @return Judgment Result     */    public static boolean isOperator(String singleStr) { String operators = "-+×÷%"; if (operators.indexOf(singleStr) > NOT_CONTAIN) {     return true; } return false;    }    private static int priority(String str) { String highOperator = "×÷%"; if (highOperator.indexOf(str) > NOT_CONTAIN) {     return HIGH_PRIORITY; } return LOW_PRIORITY;    }}