Android基础实战--实现简单计算器包含复合运算(上)


Android基础实战–实现简单计算器包含复合运算(上)

声明:
简书内容同步:https://www.jianshu.com/u/90ce902439cc
1.本文章为原创文章,转载注明出处,蟹蟹~
2.初学安卓,水平有限,还有很多不足和应当修正的地方,欢迎评论指点

先来最终效果图:
Android基础实战--实现简单计算器包含复合运算(上)_第1张图片
Android基础实战--实现简单计算器包含复合运算(上)_第2张图片
大二的java课程快结束前,想着自己用课余时间学习下安卓,于是不久前买了一本安卓开发的入门书(本人用的书是《第一行代码》,听说《疯狂安卓讲义》也不错)。在写完计算器时,java课程已结课了,时光飞逝吧。

刚好这时学院有个团队招新,发现是有安卓部分的,于是就去了解了一下,毕竟也是一个难得的机会,错过了不知道下次要等多久,团队面试对我这届安卓部分招新难度不算高,做一个基于安卓的简单计算器,要求有复合运算(括号),小数点,加减乘除功能即可。可能是因为大二上学校还没教安卓吧,要求不是很高,主要看兴趣和态度以及一点自学能力吧。
以下是具体要求:
Android基础实战--实现简单计算器包含复合运算(上)_第3张图片

Android基础实战--实现简单计算器包含复合运算(上)_第4张图片
另一个是通讯录,我没有做就暂时不在本文提及了。

Android基础实战--实现简单计算器包含复合运算(上)_第5张图片
在开始写之前我事先看了一下班上王同学用java自带的awt和swing做的用于整数运算的计算器,是一步一步算的那种。这是王同学的计算器简书链接
下面稍微详细的介绍一下具体实现步骤:
##视图部分(.xml)
最终效果就是文章最上边那样,当然一开始没有那些计算的式子。
Android基础实战--实现简单计算器包含复合运算(上)_第6张图片

由于计算器按钮的排布很容易就让我想到了javaGUI里的网格布局,虽然买的这本书上只讲了常用的几种布局,所以百度了一下安卓视图里的有没有网格布局,结果当然是有的。
做了一个小总结:
Android基础实战--实现简单计算器包含复合运算(上)_第7张图片

网格布局中除了一开始要设置layout_width,layout_height属性外,还要设置网格行数列数:rowCount,columnCount。这里我计算器按钮是5行*4列网格。
具体到网格布局里面则是按钮,我这里:

android:layout_columnWeight="1"
android:layout_rowWeight="1"

就是设置按钮在行和列的权重,我每个按钮都设置成1,所以最后每行每列都平均了,刚好是4*5网格。

<GridLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:rowCount="5"
        android:columnCount="4"
        >
<Button
            android:text="("
            android:id="@+id/buttonleft"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:textSize="30dp"
            android:textColor="#CD853F"
            android:background="#FFDAB9"/>
//...
//其他按钮同理,省略
//...
GridLayout>  

##逻辑部分(.java)
该计算器有20个按钮,功能各不相同,为每个按钮单独写监听器不现实,于是在一个监听器里面通过获取被按的按钮的ID新建一个暂时的按钮引用变量tempButton,通过获取tempButton上的text信息来判断是哪一个按钮被按了,然后再做相应的操作。
以下是实现View.OnClickListener接口重写onClick方法,当然用匿名内部类的方式也ok。

public void onClick(View v){
        Button tempButton =findViewById(v.getId());
        String tempString=(String )tempButton.getText();
        swich(tempString){
         //...
        //省略
        //...
        }
//...
//省略
//...
}

其他按钮的功能实现较为简单,其中重点是等于号按钮功能的实现,即表达式求值。

表达式求值

这里由于代码量相对较多,于是专门写了个方法去计算,参数即String类型的运表达式str。获取了表达式后首先将运算符和运算数分开。由于需要支持小数点运算,所以后边操作数都转换成double类型了。

首先从String类型上将运算符运算数分离,之后再转换类型,这里分离的方法也不唯一,这只是我个人的想法,相信肯定会有更加简便的方法。

//str为表达式,strBuffernum存运算数(以逗号隔开),strBuffersign存运算符
         StringBuffer strBuffernum=new StringBuffer() ;
         StringBuffer strBuffersign=new StringBuffer() ;
         //将运算式分开存入中, temp标记当前操作数起始下标
         for (  int temp=0,i=0; i<str.length(); i++) {
             String ele = "" + str.charAt(i);
             System.out.print(ele);
             if (ele.equals("+")||ele.equals("-")||ele.equals("*")||ele.equals("/")||ele.equals("=")||ele.equals("(")||ele.equals(")"))
             {
                 strBuffernum.append(str.substring(temp, i));
                 if(ele.equals("=")==false&&ele.equals("(")==false) {
                     strBuffernum.append(",");
                 }
                 temp=i+1;
                 strBuffersign.append(ele);
             }
         }
         String strsign =strBuffersign.toString();
         String numString= strBuffernum.toString();
         numString=numString.replace(",,", ",");//去除中间空string

其中

numString=numString.replace(",,", ",");//去除中间空string

可能会有疑问,为什么只需去掉中间的空字符串,如果第一个就是“,”那转换后还会剩一个“,”,其实这个问题在前面已经考虑,即如果以“(”开始则strBuffernum中不加“,”,结果就是遇到左括号时strBuffernum不会加任何字符串。

 if(ele.equals("=")==false&&ele.equals("(")==false) {
                     strBuffernum.append(",");
}

如果将分离后的两字符串输出则是以下效果:
字符串分离.png
为了方便计算,之后将运算数的字符串转换类型时则统一转换成double类型,让后存到ArrayList数组对象中。

      String numString= strBuffernum.toString();
          numString=numString.replace(",,", ",");//去除中间空string
      String[]  numStrArr=numString.split(",");
              Double[]  numArr = new Double[numStrArr.length];
              for(int i=0;i<numStrArr.length;i++)
             { numArr[i]=Double.valueOf(numStrArr[i]); }
 List<Double> numl = new ArrayList();
        for (int i = 0; i < numArr.length; i++) {
            if (!"".equals(numArr[i])) {
                numl.add(numArr[i]);
            }
        }

这样准备工作就完成了,之后就利用分离好的运算符字符串strsign,和ArrayList数组对象numl即可。
这里用到双栈运算式求值的方法,网上也有很多类似的解法,我这个解法仅供参考,解法并不唯一。之前看过算法第四版这本书是有这个解法解析的,但那个算法局限性比较高,对表达式的形式有一定要求,没有省略任何括号, 比如平常的1+2×3要求为:(1+(2×3)) 。也想过怎么把一般式子改写成标准式,后来还是直接对已有式子求值了,想法很相似。
我会在我的下一篇文章中分别用栈和链表解一遍,也算是复习一下数据结构吧,其实基本思路是完全一样的,只是换一种存数和存符的数据类型而已。

你可能感兴趣的:(#,Android开发入门)