Android实现简单计算器

前言

在学习了Android第一行代码的前三章后开始了自己的第一个android小项目,由于接触android时间不长,再加上个人审美能力较差,因此界面做的不是很好,大致可以体现出来一个计算器的界面。。。实现简单的计算器并不难,只要掌握了活动,布局以及控件的基本使用就可以开发出一个简单的android版计算器了

界面部分

我外层用的是外层相对布局,然后内层有四个线性布局加一个TextView控件,由于刚开始学,理解还不是特别深,因此布局这块写的可能感觉有点乱。。因为内层的线性布局采用了垂直布局,所以才写成了这样。。其实可以整体采用百分比布局或者外层垂直线性布局,内层水平线性布局,这样会比较清楚一点,以下是我的布局代码

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">    <LinearLayout        android:id="@+id/jiemian"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true">        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"            android:id="@+id/first"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom"            android:layout_weight="1"            android:orientation="vertical">            <Button                android:id="@+id/symbol_ac"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="#f5f5f5"                android:text="AC"                android:textColor="#007dfe"                android:textSize="24sp" />            <Button                android:id="@+id/number_7"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="7"                android:textSize="24sp" />            <Button                android:id="@+id/number_4"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="4"                android:textSize="24sp" />            <Button                android:id="@+id/number_1"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="1"                android:textSize="24sp" />            <Button                android:id="@+id/symbol_left"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="("                android:textSize="24sp" />        LinearLayout>        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"            android:id="@+id/second"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom"            android:layout_weight="1"            android:orientation="vertical">            <Button                android:id="@+id/symbol_div"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="#f5f5f5"                android:text="/"                android:textColor="#007dfe"                android:textSize="24sp" />            <Button                android:id="@+id/number_8"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="8"                android:textSize="24sp" />            <Button                android:id="@+id/number_5"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="5"                android:textSize="24sp" />            <Button                android:id="@+id/number_2"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="2"                android:textSize="24sp" />            <Button                android:id="@+id/number_0"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="0"                android:textSize="24sp" />        LinearLayout>        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"            android:id="@+id/third"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom"            android:layout_weight="1"            android:orientation="vertical">            <Button                android:id="@+id/symbol_mult"                android:layout_width="match_parent"                android:layout_height="85dp"                android:background="#f5f5f5"                android:text="×"                android:textColor="#007dfe"                android:textSize="30sp" />            <Button                android:id="@+id/number_9"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="9"                android:textSize="24sp" />            <Button                android:id="@+id/number_6"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="6"                android:textSize="24sp" />            <Button                android:id="@+id/number_3"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text="3"                android:textSize="24sp" />            <Button                android:id="@+id/symbol_right"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="@android:color/white"                android:text=")"                android:textSize="24sp" />        LinearLayout>        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"            android:id="@+id/end"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom"            android:layout_weight="1"            android:orientation="vertical">            <Button                android:id="@+id/symbol_del"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="#f5f5f5"                android:text="←"                android:textColor="#007dfe"                android:textSize="30sp" />            <Button                android:id="@+id/symbol_sub"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="#f5f5f5"                android:text="-"                android:textColor="#007dfe"                android:textSize="24sp" />            <Button                android:id="@+id/symbol_add"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="#f5f5f5"                android:text="+"                android:textColor="#007dfe"                android:textSize="24sp" />            <Button                android:id="@+id/symbol_dian"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="1"                android:background="#f5f5f5"                android:text="."                android:textColor="#007dfe"                android:textSize="24sp" />            <Button                android:id="@+id/symbol_equal"                android:layout_width="match_parent"                android:layout_height="85dp"                android:layout_weight="2"                android:background="#007dfe"                android:text="="                android:textColor="@android:color/white"                android:textSize="24sp" />        LinearLayout>    LinearLayout>    <TextView        android:id="@+id/text_view"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentStart="true"        android:layout_alignParentTop="true"        android:layout_marginTop="90dp"        android:maxLines="1"        android:textSize="24sp" />RelativeLayout>

逻辑部分

在计算方面采用了中缀表达式转后缀表达式,然后后缀表达式计算得出结果。参考以下两篇文章:
将中缀表达式转化为后缀表达式
后缀表达式的计算
代码如下

package com.example.yjh.test;import java.math.BigDecimal;import java.util.ArrayDeque;public class Calculator {    //计算表达式的值    public String caculate(String string) throws Exception {        //该部分用来验证中缀表达式是否合理        //若右括号数量大于左括号,则说明表达式不合理,抛出异常        //否则说明正常,继续进行运算        int x = 0;        for (int i = 0; i < string.length(); i++) {            if (string.charAt(i) == '(') {                x++;            } else if (string.charAt(i) == ')') {                x--;            }        }        if (x < 0) {            throw new Exception("错误,右括号数量大于左括号");        }        //该集合用来存储操作数        ArrayDeque value = new ArrayDeque<>();        //该集合用来存储运算符        ArrayDeque operation = new ArrayDeque<>();        //该字符串用来临时存储转化后的后缀表达式        StringBuilder stringBuilder = new StringBuilder();        //将中缀表达式的操作数和运算符分离并存放到字符串数组中        String[] expression = formatInput(string);        //遍历字符串数组        for (String s : expression) {            //若该字符串为空则跳过            if (s.equals(" ") || s.length() == 0) {                continue;            } else if (s.charAt(0) == '-' && !s.equals("-")) {    //若为是负数,则添加至后缀表达式末尾,并补上空格,方便后面将后缀表达式分离                stringBuilder.append(s + " ");            } else if (isDigital(s.charAt(0))) {    //若为正数,添加至后缀表达式并补空格                stringBuilder.append(s + " ");            } else if (isOperater(s.charAt(0)) || s.charAt(0) == '(' || s.charAt(0) == ')') {    //若为运算符,继续判断                if (s.equals("(")) {//若为左括号,则压入运算符栈中                    operation.push(s);                    continue;                }                //若为右括号,则将运算符栈中第一个左括号以上全部弹出并添加至后缀表达式,左括号直接弹出,不用添加至后缀表达式                if (s.equals(")")) {                    while (!operation.getFirst().equals("(")) {                        if (!operation.getFirst().equals("(")) {                            stringBuilder.append(operation.poll()+" ");                        }                    }                    if (operation.getFirst().equals("(")) {                        operation.pop();                        continue;                    }                }                //若运算符栈为空,则将运算符压入栈中                if (operation.isEmpty()) {                    operation.push(s);                    continue;                } else if (priorityIsBiggerOrTheSame(s, operation.getFirst())) {    //若该运算符比栈顶运算符优先级高,则压入栈中                    operation.push(s);                    continue;                } else {    //否则弹出所有优先级不比它低的运算符并添加至后缀表达式                    while (!operation.isEmpty() && !priorityIsBiggerOrTheSame(s, operation.getFirst())) {                        stringBuilder.append(operation.poll() +" ");                    }                    operation.push(s);                    continue;                }            }        }        //弹出操作数栈中所有元素并添加至后缀表达式        while (!operation.isEmpty()) {            stringBuilder.append(operation.poll());        }        //格式化后缀表达式(将操作数与运算符分离)        expression = formatInfixExpression(stringBuilder.toString());        //清空后缀表达式        stringBuilder.delete(0, stringBuilder.length());        //遍历字符串数组        for (String s : expression) {            //若该字符串为空,则跳过            if (s.equals(" ") || s.length() == 0) {                continue;            } else if (isDigital(s.charAt(0))) {    //若为正数则压入操作数栈中                value.push(s);            } else if (s.charAt(0) == '-' && !s.equals("-")) {    //若为负数,则压入操作数栈中                value.push(s);            } else if (isOperater(s.charAt(0))) {    //若为运算符,则判断操作数个数大于2个,则进行弹出两个操作数进行操作,然后将结果压入操作数栈中                if (value.size() >= 2) {                    BigDecimal last = new BigDecimal(value.poll());                    BigDecimal last_p = new BigDecimal(value.poll());                    if (s.equals("-")) {                        value.push(last_p.subtract(last).toString());                    } else if (s.equals("+")) {                        value.push(last_p.add(last).toString());                    } else if (s.equals("*")) {                        value.push(last_p.multiply(last).toString());                    } else if (s.equals("/")) {                        value.push(last_p.divide(last, 15, BigDecimal.ROUND_HALF_DOWN).toString());                    }                }            }        }        //弹出最终运算结果并返回        return value.poll();    }    //判断是否为运算符,若为运算符,则返回true,否则返回false    public static boolean isOperater(int a) {        if (a == '+' || a == '-' || a == '*' || a == '/')            return true;        return false;    }    //判断是否为数字,若为数字,则返回true,否则返回false    public static boolean isDigital(int a) {        if (a >= '0' && a <= '9')            return true;        return false;    }    // 格式化中缀表达式输入,即在符号前后添加空格,便于后面的分隔操作    public static String[] formatInput(String s) {        String temp = "";        for (int i = 0; i < s.length(); i++) {            char c = s.charAt(i);            if (i == 0 && c == '-') {                temp += c;            } else if (isOperater(c) || c == '(' || c == ')') {                if ((i - 1) >= 0 && (i + 1) < s.length()                        && (isOperater(s.charAt(i - 1)) || s.charAt(i - 1) == '(' || s.charAt(i - 1) == ' ')                        && c == '-' && isDigital(s.charAt(i + 1))) {                    temp += " " + c;                } else {                    temp += " " + c + " ";                }            } else                temp += c;// 数字不用加空格        }        return temp.split(" ");// 分割    }    //格式化后缀表达式    public static String[] formatInfixExpression(String s) {        String temp = "";        for (int i = 0; i < s.length(); i++) {            char c = s.charAt(i);            if (isOperater(c)) {                if (c == '-' && i + 1 < s.length() && isDigital(s.charAt(i + 1))) {                    temp += " " + c;                } else {                    temp += " " + c + " ";                }            } else {                temp += c;// 数字不用加空格            }        }        return temp.split(" ");// 分割    }    // 优先级判断,a是否大于b    public static boolean priorityIsBiggerOrTheSame(String a, String b) {        String s = " +- */";        return s.indexOf(a) - s.indexOf(b) >= 2;    }}

在主活动部分获取了按钮的实例,然后为按钮创建点击事件,并在用户输入时做了一些限制。部分限制如下(还有一些限制没有列出来,在代码中体现):

  • 一个操作数不能有两个小数点
  • 左括号不能和运算符直接相连,符号除外
  • 当数字和右括号相连时,自动在数字和右括号之间补上乘号

代码如下:

import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.text.method.ScrollingMovementMethod;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private TextView textView;    public StringBuilder results = new StringBuilder();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button0 = (Button) findViewById(R.id.number_0);        Button button1 = (Button) findViewById(R.id.number_1);        Button button2 = (Button) findViewById(R.id.number_2);        Button button3 = (Button) findViewById(R.id.number_3);        Button button4 = (Button) findViewById(R.id.number_4);        Button button5 = (Button) findViewById(R.id.number_5);        Button button6 = (Button) findViewById(R.id.number_6);        Button button7 = (Button) findViewById(R.id.number_7);        Button button8 = (Button) findViewById(R.id.number_8);        Button button9 = (Button) findViewById(R.id.number_9);        Button button_add = (Button) findViewById(R.id.symbol_add);        Button button_sub = (Button) findViewById(R.id.symbol_sub);        Button button_mult = (Button) findViewById(R.id.symbol_mult);        Button button_div = (Button) findViewById(R.id.symbol_div);        Button button_del = (Button) findViewById(R.id.symbol_del);        Button button_dian = (Button) findViewById(R.id.symbol_dian);        Button button_equal = (Button) findViewById(R.id.symbol_equal);        Button button_left = (Button) findViewById(R.id.symbol_left);        Button button_right = (Button) findViewById(R.id.symbol_right);        Button button_ac = (Button) findViewById(R.id.symbol_ac);        this.textView = (TextView) findViewById(R.id.text_view);        textView.setMovementMethod(ScrollingMovementMethod.getInstance());        button0.setOnClickListener(this);        button1.setOnClickListener(this);        button2.setOnClickListener(this);        button3.setOnClickListener(this);        button4.setOnClickListener(this);        button5.setOnClickListener(this);        button6.setOnClickListener(this);        button7.setOnClickListener(this);        button8.setOnClickListener(this);        button9.setOnClickListener(this);        button_add.setOnClickListener(this);        button_sub.setOnClickListener(this);        button_mult.setOnClickListener(this);        button_div.setOnClickListener(this);        button_del.setOnClickListener(this);        button_dian.setOnClickListener(this);        button_left.setOnClickListener(this);        button_ac.setOnClickListener(this);        button_right.setOnClickListener(this);        button_equal.setOnClickListener(this);    }    @Override    public void onClick(View view) {        int last = 0;        int last_p = 0;        if (results.length() != 0) {            last = results.codePointAt(results.length() - 1);            if (results.length() > 1)                last_p = results.codePointBefore(results.length() - 1);        }        if (results.indexOf("=") > 0) {            results.replace(0, results.length(), "");        }        switch (view.getId()) {            case R.id.number_0:                if (last == ')') {                    results.append("*0");                } else {                    results.append('0');                }                textView.setText(results);                break;            case R.id.number_1:                if (last == ')') {                    results.append("*1");                } else {                    results.append('1');                }                textView.setText(results);                break;            case R.id.number_2:                if (last == ')') {                    results.append("*2");                } else {                    results.append('2');                }                textView.setText(results);                break;            case R.id.number_3:                if (last == ')') {                    results.append("*3");                } else {                    results.append('3');                }                textView.setText(results);                break;            case R.id.number_4:                if (last == ')') {                    results.append("*4");                } else {                    results.append('4');                }                textView.setText(results);                break;            case R.id.number_5:                if (last == ')') {                    results.append("*5");                } else {                    results.append('5');                }                textView.setText(results);                break;            case R.id.number_6:                if (last == ')') {                    results.append("*6");                } else {                    results.append('6');                }                textView.setText(results);                break;            case R.id.number_7:                if (last == ')') {                    results.append("*7");                } else {                    results.append('7');                }                textView.setText(results);                break;            case R.id.number_8:                if (last == ')') {                    results.append("*8");                } else {                    results.append('8');                }                textView.setText(results);                break;            case R.id.number_9:                if (last == ')') {                    results.append(" * 9");                } else {                    results.append('9');                }                textView.setText(results);                break;            case R.id.symbol_add:                if (isDigital(last) || last == ')' || last == '.') {                    results.append('+');                } else if (isOperater(last) && isOperater(last_p)) {                    results.replace(results.length() - 2, results.length(), "+");                } else if (isOperater(last)) {                    results.setCharAt(results.length() - 1, '+');                } else {                    Toast.makeText(MainActivity.this, "错误",                            Toast.LENGTH_SHORT).show();                }                textView.setText(results);                break;            case R.id.symbol_sub:                if (isDigital(last) || last == ')' || last == '(' || last == '.') {                    results.append('-');                } else if (last == '-' || last == '+') {                    results.setCharAt(results.length() - 1, '-');                } else if (last == '*' || last == '/') {                    results.append('-');                } else if (results.length() == 0) {                    results.append('-');                } else {                    Toast.makeText(MainActivity.this, "错误",                            Toast.LENGTH_SHORT).show();                }                textView.setText(results);                break;            case R.id.symbol_mult:                if (isDigital(last) || last == ')' || last == '.') {                    results.append('*');                } else if (isOperater(last)) {                    results.setCharAt(results.length() - 1, '*');                } else if (isOperater(last) && isOperater(last_p)) {                    results.replace(results.length() - 2, results.length(), "*");                } else {                    Toast.makeText(MainActivity.this, "错误",                            Toast.LENGTH_SHORT).show();                }                textView.setText(results);                break;            case R.id.symbol_div:                if (isDigital(last) || last == ')' || last == '.') {                    results.append('/');                } else if (isOperater(last) && isOperater(last_p)) {                    results.replace(results.length() - 2, results.length(), "/");                } else if (isOperater(last)) {                    results.setCharAt(results.length() - 1, '/');                } else {                    Toast.makeText(MainActivity.this, "错误",                            Toast.LENGTH_SHORT).show();                }                textView.setText(results);                break;            case R.id.symbol_del:                if (results.indexOf("=") > 0) {                    results.replace(0, results.length(), "");                } else if (results.length() > 0) {                    results.deleteCharAt(results.length() - 1);                }                textView.setText(results);                break;            case R.id.symbol_ac:                results.delete(0, results.length());                textView.setText(results);                break;            case R.id.symbol_dian:                int index = results.lastIndexOf(".");                boolean flag = false;                for (int i = index; i > 0 && i < results.length(); i++) {                    int x = results.charAt(i);                    if (isOperater(x) || x == '(' || x==')') {                        flag = true;                        break;                    }                }                if ((isDigital(last) && flag) || (isDigital(last) && index<0)) {                    results.append('.');                } else {                    Toast.makeText(MainActivity.this, "错误",                            Toast.LENGTH_SHORT).show();                }                textView.setText(results);                break;            case R.id.symbol_left:                if (last == '-' && isOperater(last_p)) {                    results.replace(results.length() - 1, results.length(), "(-");                } else if (isDigital(last)) {                    results.append("*(");                } else if (isOperater(last)) {                    results.append('(');                } else if (last == ')') {                    results.append("*(");                } else if (last == '(') {                    results.append('(');                } else if (results.length() == 0) {                    results.append('(');                } else {                    Toast.makeText(MainActivity.this, "错误",                            Toast.LENGTH_SHORT).show();                }                textView.setText(results);                break;            case R.id.symbol_right:                if (isDigital(last) || last == ')') {                    results.append(')');                } else {                    Toast.makeText(MainActivity.this, "错误",                            Toast.LENGTH_SHORT).show();                }                textView.setText(results);                break;            case R.id.symbol_equal:                try {                    Calculator calculator = new Calculator();                    results.replace(0, results.length(), calculator.caculate(results.toString()));                    textView.setText(results);                } catch (Exception e) {                    textView.setText(e.getMessage());                    results.replace(0, results.length(), "");                }            default:                break;        }    }    public static boolean isOperater(int a) {        if (a == '+' || a == '-' || a == '*' || a == '/')            return true;        return false;    }    public static boolean isDigital(int a) {        if (a >= '0' && a <= '9')            return true;        return false;    }}

更多相关文章

  1. 【android工程转为lib工程后提示'R.id.xxx不能作为case语句的表
  2. Android--取出SDcard卡上指定后缀名的文件
  3. Android Studio 使用 Lambda表达式
  4. android 正则表达式
  5. Mac版Android studio中使用lambda表达式设置jdk版本问题
  6. Android 正则表达式验证手机和邮箱格式是否正确
  7. Android Studio中快速替换styles的正则表达式
  8. lambda表达式进行对象结合操作的实例详解
  9. C#中匿名委托以及Lambda表达式的实例详解

随机推荐

  1. CenOS6.7下mysql 8.0.22 安装配置方法图
  2. 推荐几款MySQL相关工具
  3. Windows10下mysql 8.0.22 安装配置方法图
  4. 浅析MySQL的lru链表
  5. mysql 5.5.27 winx64安装配置方法图文教
  6. mysql 8.0.22 winx64安装配置方法图文教
  7. mysql 8.0.22 下载安装配置方法图文教程
  8. MySQL 各个索引的使用详解
  9. MySQL的查询缓存和Buffer Pool
  10. 浅析MySQL的基数统计