美文网首页
基于databinding实现Android简易计算器

基于databinding实现Android简易计算器

作者: casuality4windy | 来源:发表于2017-10-15 13:38 被阅读0次
    Gradle配置

     项目需要使用databinding特性,需要配置下build.gradle(Module)

    android{
      ...
      dataBinding{
            enabled true
        }
    }
    

     没有接触过databinding的同学可以移步此页面
    https://github.com/LyndonChin/MasteringAndroidDataBinding

    界面设计

     ... 就是TextView + N个Button的搭配,本人缺乏艺术细胞,详情请点击
    http://www.sj33.cn/digital/uisj/201609/46378.html
     本人设计的界面效果如下

    • UI
    UI UI
    代码设计

     代码结构(很简单...)

    code.png
    • Compute
      对中缀表达式转换成后缀表达式,并计算结果。
    public class Compute {
         public static String c(String infixExp){
            String result;
            try {
                List<Object> posfix = infix2posfix(infixExp);
                result = f(posfix);
            }catch (Exception e){
                result = Values.IRREGULAR_EXP;
            }
            return result;
        }
    
        private static String f(List<Object> list) {
            Stack<BigDecimal> result = new Stack<>();
            Iterator it = list.iterator();
            while(it.hasNext()){
                String m = it.next().toString();
                if (m.equals(Values.ACTION_ADD)
                        || m.equals(Values.ACTION_SUB)
                        || m.equals(Values.ACTION_MUL)
                        || m.equals(Values.ACTION_DIV)) {
                    BigDecimal b = result.pop();
                    BigDecimal a = result.pop();
                    BigDecimal v = g(a, b, m);
                    result.push(v);
                }else {
                    result.push(new BigDecimal(m));
                }
            }
            return(result.pop().toString());
        }
    
        private static BigDecimal g(BigDecimal a, BigDecimal b, String m) {
            BigDecimal v = new BigDecimal("0.0");
            switch (m) {
                case Values.ACTION_ADD:
                    v = a.add(b);
                    break;
                case Values.ACTION_SUB:
                    v = a.subtract(b);
                    break;
                case Values.ACTION_MUL:
                    v = a.multiply(b);
                    break;
                case Values.ACTION_DIV:
                    v = a.divide(b, Values.DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP);
                    break;
            }
            return v;
        }
    
        private static List<Object> infix2posfix(String s) {
            Stack<Character> opsStack = new Stack<>();
            ArrayList<Object> list = new ArrayList<>();
            Pattern P = Pattern.compile("[0-9]+(\\.[0-9]+)?");   //正则表达式来处理带小数点的数字
            int i=0;
    
            while(i < s.length()){
                char c = s.charAt(i);
                if (c >='0' && c <= '9') {
                    String subStr = s.substring(i);
                    Matcher m = P.matcher(subStr);
                    if (m.find()) {    //取匹配到的第一个数字
                        subStr = m.group();
                        list.add(subStr);
                    }
                    i = i + subStr.length();
                    continue;
                } else if (c == '(') {
                    opsStack.push(c);
                } else if (c == ')') {
                    while(opsStack.peek() != '('){
                        list.add(opsStack.pop());
                    }
                    //pop the '('
                    opsStack.pop();
                } else if (c == '+' || c == '-') {
                    while(!opsStack.isEmpty() && opsStack.peek() != '('){
                        list.add(opsStack.pop());
                    }
                    opsStack.push(c);
                }else if (c == '*'|| c == '/') {
                    while(!opsStack.isEmpty() && (opsStack.peek() =='*' || opsStack.peek() == '/')){
                        list.add(opsStack.pop());
                    }
                    opsStack.push(c);
                }
                i++;
            }
    
            while(!opsStack.isEmpty()){
                list.add(opsStack.pop());
            }
            return list;
        }
    }
    
    • Update
      初始化按钮响应事件,并更新表达式,得数。
    public class Update {
        private static String result = "";
        public static void btnClickEventInit(final ActivityMainBinding binding){
            /**
             * inti number event
             */
            binding.btnZero.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    appendText(binding, "0");
                }
            });
    
            binding.btnOne.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    appendText(binding, "1");
                }
            });
          
          ... ...
    
            binding.btnDot.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String exp = binding.textExp.getText().toString();
                    if (isDotabled(exp)) {
                        appendText(binding, ".");
                    }
                }
            });
    
            /**
             * init compute event
             */
            binding.btnAdd.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String exp = binding.textExp.getText().toString();
                    if (isOperateable(exp)){
                        appendResultText(binding, "+");
                    }
                }
            });
    
            ... ...
    
            binding.btnEqual.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String exp = binding.textExp.getText().toString();
                    result = Compute.c(exp);
    
                    binding.textExp.setText("");
                    binding.textResult.setText(result);
                }
            });
    
            /**
             * init clear & delete
             */
            binding.btnClear.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    clearText(binding);
                }
            });
    
            binding.btnDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    deleteText(binding);
                }
            });
        }
    
        /**
         * Handle text
         */
        private static void appendText(final ActivityMainBinding binding, String append){
            String oldExp = binding.textExp.getText().toString();
            binding.setExpress(oldExp + append);
        }
    
        private static void clearText(final ActivityMainBinding binding){
            result = "";
            binding.setExpress("");
            binding.setResult("");
        }
    
        private static void deleteText(final ActivityMainBinding binding){
            String oldExp = binding.textExp.getText().toString();
            if (oldExp != "") {
                StringBuilder builder = new StringBuilder(oldExp);
                binding.setExpress(builder.deleteCharAt(builder.length() - 1).toString());
            }
        }
    
        private static void appendResultText(ActivityMainBinding binding, String op){
            if (binding.textExp.getText().toString() != "") {
                appendText(binding, op);
            }
            else {
                appendText(binding, result + op);
            }
        }
    
        /**
         * check text
         */
        private static boolean isOperateable(String exp){
            if ((result != "" && result != Values.IRREGULAR_EXP)
                || (exp != "" && Character.isDigit(exp.charAt(exp.length() - 1)))) {
                return true;
            }
            return false;
        }
    
        private static boolean isDotabled(String exp){
            int lastPos = exp.length() - 1;
            if (exp != ""
                    && ('0' <= exp.charAt(lastPos) && exp.charAt(lastPos) <= '9')) {
                for (int i = exp.length() - 1; i >= 0; i--) {
                    if (exp.charAt(i) == '.') {
                        return false;
                    } else if (exp.charAt(i) == '+'
                            || exp.charAt(i) == '-'
                            || exp.charAt(i) == '*'
                            || exp.charAt(i) == '/') {
                        return true;
                    }
                }
                return true;
            }
            return false;
        }
    }
    
    • Values
      就是一些变量咯...
    public class Values {
        public static final String IRREGULAR_EXP = "错误";
        public static final String ACTION_ADD = "+";
        public static final String ACTION_SUB = "-";
        public static final String ACTION_MUL = "*";
        public static final String ACTION_DIV = "/";
        public static final int DEF_DIV_SCALE = 10;
    }
    
    难点
    • 中缀表达式的计算,借助栈将中缀表达式转换成后缀表达式,进而计算结果
    • 浮点数的计算,起先用double类型时,会出现 0.3 * 6 = 1.7999999的bug,后采用BigDemical成功debug
    • 表达式的规范,表达式末为数字时可以输入操作符(+-*/), 表达式末为数字且此数不为小数时可加小数点等
    • databinding的使用,项目采用了单向数据绑定,简化了button等组件的初始化过程
    不足
    • 未实现负数计算功能
    • 未实现科学计算功能

    相关文章

      网友评论

          本文标题:基于databinding实现Android简易计算器

          本文链接:https://www.haomeiwen.com/subject/vzaquxtx.html