代码地址
https://github.com/xjhqre/android_calculator
效果演示
1. 连续加法
2. 连续减法
3. 连续乘法
4. 连续除法
5. 优先级运算
6. 退格功能
7. 错误提示
制作步骤
1. 创建按钮图片
1.1. 退格图形
<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="200dp"android:height="200dp"android:viewportWidth="1024"android:viewportHeight="1024"><pathandroid:pathData="M484.46,627.9a28.77,28.77 0,0 1,-20.34 -49.11l174.27,-174.27a28.77,28.77 0,0 1,40.68 40.68l-174.27,174.28a28.69,28.69 0,0 1,-20.34 8.42z"android:fillColor="#0099FF"/><pathandroid:pathData="M658.73,627.9a28.68,28.68 0,0 1,-20.34 -8.42l-174.27,-174.28a28.76,28.76 0,0 1,0 -40.68,28.75 28.75,0 0,1 40.68,0l174.27,174.27a28.78,28.78 0,0 1,-20.34 49.11z"android:fillColor="#0099FF"/><pathandroid:pathData="M834.54,821.19H340.57c-28.47,0 -55.25,-12.54 -73.49,-34.39L75.76,556.98c-10.55,-13.06 -16.2,-28.92 -16.2,-44.99 0.01,-15.39 4.67,-29.85 13.5,-41.81 0.34,-0.46 0.68,-0.9 1.05,-1.33L266.71,237.63a95.32,95.32 0,0 1,73.86 -34.83H834.54c51.98,0 94.28,42.29 94.28,94.27v429.84c0,51.98 -42.29,94.28 -94.28,94.28zM119.02,504.83c-0.91,1.36 -1.92,3.52 -1.92,7.18 0,2.92 1.15,6.02 3.16,8.5l191.02,229.45a38.56,38.56 0,0 0,29.29 13.69H834.54a36.78,36.78 0,0 0,36.75 -36.75v-429.84a36.78,36.78 0,0 0,-36.75 -36.74H340.57a38.61,38.61 0,0 0,-29.54 13.97L119.02,504.83z"android:fillColor="#0099FF"/>
</vector>
1.2. 等号图形
<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="200dp"android:height="200dp"android:viewportWidth="1024"android:viewportHeight="1024"><pathandroid:pathData="M524,927.3c-224.8,0 -407.8,-182.9 -407.8,-407.8s183,-407.7 407.8,-407.7 407.7,182.9 407.7,407.8S748.8,927.3 524,927.3zM524,176.6c-189.1,0 -342.9,153.8 -342.9,342.9s153.8,343 342.9,343c189.1,0 342.9,-153.8 342.9,-342.9s-153.8,-343 -342.9,-343z"android:fillColor="#0099FF"/><pathandroid:pathData="M697.1,452.2H350.9c-17.9,0 -32.4,-14.5 -32.4,-32.4s14.5,-32.4 32.4,-32.4h346.2c17.9,0 32.4,14.5 32.4,32.4s-14.5,32.4 -32.4,32.4zM697.1,635.6H350.9c-17.9,0 -32.4,-14.5 -32.4,-32.4s14.5,-32.4 32.4,-32.4h346.2c17.9,0 32.4,14.5 32.4,32.4s-14.5,32.4 -32.4,32.4z"android:fillColor="#0099FF"/>
</vector>
2. 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/et_record"android:layout_width="match_parent"android:layout_height="150dp"android:gravity="right"android:text=""android:textSize="60sp"tools:ignore="RtlHardcoded" /><TextViewandroid:id="@+id/et_result"android:layout_width="match_parent"android:layout_height="70dp"android:gravity="right"android:text=""android:textSize="40sp"tools:ignore="RtlHardcoded" /><GridLayoutandroid:layout_width="match_parent"android:layout_gravity="center"android:layout_weight="1"android:columnCount="4"android:orientation="horizontal"android:rowCount="5" android:layout_height="0dp"><Buttonandroid:id="@+id/btn_clear"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="AC"android:textColor="#0099FF"android:textSize="26sp" /><ImageButtonandroid:id="@+id/btn_delete"android:layout_width="1dp"android:layout_height="1dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:scaleType="fitCenter"android:scaleX="0.5"android:scaleY="0.5"android:src="@drawable/ic_del" /><Buttonandroid:id="@+id/btn_percentSign"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="%"android:textColor="#0099FF"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_div"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="÷"android:textColor="#0099FF"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_1"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="1"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_2"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="2"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_3"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="3"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_mul"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="×"android:textColor="#0099FF"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_4"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="4"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_5"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="5"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_6"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="6"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_sub"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="-"android:textColor="#0099FF"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_7"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="7"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_8"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="8"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_9"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="9"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_add"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="+"android:textColor="#0099FF"android:textSize="26sp" /><Buttonandroid:id="@+id/btn_null"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text=""android:textSize="26sp" /><Buttonandroid:id="@+id/btn_dot"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="."android:textSize="26sp" /><Buttonandroid:id="@+id/btn_0"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:text="0"android:textSize="26sp" /><ImageButtonandroid:id="@+id/btn_equ"android:layout_width="1dp"android:layout_height="1dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:background="@null"android:scaleType="centerInside"android:scaleX="0.6"android:scaleY="0.6"android:src="@drawable/ic_equl"android:textColor="#0099FF"android:textSize="26sp" /></GridLayout></LinearLayout>
3. java代码
package com.example.work2;import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;import java.util.ArrayList;public class MainActivity extends AppCompatActivity {Button btn_1; // 数字1Button btn_2; // 数字2Button btn_3; // 数字3Button btn_4; // 数字4Button btn_5; // 数字5Button btn_6; // 数字6Button btn_7; // 数字7Button btn_8; // 数字8Button btn_9; // 数字9Button btn_0; // 数字0Button add; // +号Button sub; // -号Button mul; // *号Button div; // 除号Button dot; // 小数点ImageButton equ; // =号ImageButton backspace; // 退格符号Button percentSign; // %Button ac; //清除TextView result; // 显示结果TextView record; // 显示记录String record_string; // String类型的运算步骤ArrayList<String> operatorStack = new ArrayList<>();ArrayList<Double> operandStack = new ArrayList<>();ArrayList<String> operatorList = new ArrayList<>();int previousOperatorSubscript = 0;int nextOperatorSubscript = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);operatorList.add("+");operatorList.add("-");operatorList.add("×");operatorList.add("÷");// 获取页面上的控件btn_1 = findViewById(R.id.btn_1);btn_2 = findViewById(R.id.btn_2);btn_3 = findViewById(R.id.btn_3);btn_4 = findViewById(R.id.btn_4);btn_5 = findViewById(R.id.btn_5);btn_6 = findViewById(R.id.btn_6);btn_7 = findViewById(R.id.btn_7);btn_8 = findViewById(R.id.btn_8);btn_9 = findViewById(R.id.btn_9);btn_0 = findViewById(R.id.btn_0);add = findViewById(R.id.btn_add);sub = findViewById(R.id.btn_sub);mul = findViewById(R.id.btn_mul);div = findViewById(R.id.btn_div);equ = findViewById(R.id.btn_equ);dot = findViewById(R.id.btn_dot);ac = findViewById(R.id.btn_clear);percentSign = findViewById(R.id.btn_percentSign);backspace = findViewById(R.id.btn_delete);record = findViewById(R.id.et_record);result = findViewById(R.id.et_result);// 按钮的单击事件btn_1.setOnClickListener(new Click());btn_2.setOnClickListener(new Click());btn_3.setOnClickListener(new Click());btn_4.setOnClickListener(new Click());btn_5.setOnClickListener(new Click());btn_6.setOnClickListener(new Click());btn_7.setOnClickListener(new Click());btn_8.setOnClickListener(new Click());btn_9.setOnClickListener(new Click());btn_0.setOnClickListener(new Click());add.setOnClickListener(new Click());sub.setOnClickListener(new Click());mul.setOnClickListener(new Click());div.setOnClickListener(new Click());equ.setOnClickListener(new Click());dot.setOnClickListener(new Click());ac.setOnClickListener(new Click());backspace.setOnClickListener(new Click());percentSign.setOnClickListener(new Click());}// 设置按钮点击后的监听class Click implements View.OnClickListener {@RequiresApi(api = Build.VERSION_CODES.N)@SuppressLint("NonConstantResourceId")public void onClick(View v) {switch (v.getId()) { //switch循环获取点击按钮后的值case R.id.btn_0: //获取,0-9、小数点,并在编辑框显示record_string = record.getText().toString();record_string += "0";record.setText(record_string);break;case R.id.btn_1:record_string = record.getText().toString();record_string += "1";record.setText(record_string);break;case R.id.btn_2:record_string = record.getText().toString();record_string += "2";record.setText(record_string);break;case R.id.btn_3:record_string = record.getText().toString();record_string += "3";record.setText(record_string);break;case R.id.btn_4:record_string = record.getText().toString();record_string += "4";record.setText(record_string);break;case R.id.btn_5:record_string = record.getText().toString();record_string += "5";record.setText(record_string);break;case R.id.btn_6:record_string = record.getText().toString();record_string += "6";record.setText(record_string);break;case R.id.btn_7:record_string = record.getText().toString();record_string += "7";record.setText(record_string);break;case R.id.btn_8:record_string = record.getText().toString();record_string += "8";record.setText(record_string);break;case R.id.btn_9:record_string = record.getText().toString();record_string += "9";record.setText(record_string);break;case R.id.btn_dot:record_string = record.getText().toString();record_string += ".";record.setText(record_string);break;case R.id.btn_add: //判断,使用加减乘除的操作符record_string = record.getText().toString();record_string += "+";record.setText(record_string);break;case R.id.btn_sub:record_string = record.getText().toString();record_string += "-";record.setText(record_string);break;case R.id.btn_mul:record_string = record.getText().toString();record_string += "×";record.setText(record_string);break;case R.id.btn_div:record_string = record.getText().toString();record_string += "÷";record.setText(record_string);break;case R.id.btn_delete:record_string = record.getText().toString();if (record_string.length() > 0) {record_string = record_string.substring(0, record_string.length() - 1);record.setText(record_string);}break;case R.id.btn_clear: //清除,将编辑框文本显示为空record.setText(null);result.setText(null);previousOperatorSubscript = 0;nextOperatorSubscript = 0;operandStack.clear();operatorStack.clear();break;case R.id.btn_equ: //计算,以操作符为判断,选择所需的运算,并将结果输出if ("错误".equals(result.getText().toString())) return;record_string = record.getText().toString();if ("".equals(record_string)) return;// 遍历运算记录,调整运算优先级,使运算记录中只剩下加减操作for (int i = 0; i < record_string.length(); i++) {String operator = String.valueOf(record_string.charAt(i));// 如果遍历到运算符if (operatorList.contains(operator)) {// 插入新的操作数nextOperatorSubscript = i;try {operandStack.add(Double.parseDouble(record_string.substring(previousOperatorSubscript, nextOperatorSubscript)));} catch (Exception e) {result.setText("错误");return;}previousOperatorSubscript = nextOperatorSubscript + 1;// 如果运算符栈中没有运算符if (operatorStack.size() == 0) {operatorStack.add(operator);} else {// 找出上一个运算符String pre_operator = operatorStack.get(operatorStack.size() - 1);if ("×".equals(pre_operator)) {// 移除上一个运算符operatorStack.remove(operatorStack.size() - 1);Double num1 = operandStack.get(operandStack.size() - 2);Double num2 = operandStack.get(operandStack.size() - 1);operandStack.remove(operandStack.size() - 1);operandStack.remove(operandStack.size() - 1);operandStack.add(num1 * num2);} else if ("÷".equals(pre_operator)) {// 移除上一个运算符operatorStack.remove(operatorStack.size() - 1);Double num1 = operandStack.get(operandStack.size() - 2);Double num2 = operandStack.get(operandStack.size() - 1);operandStack.remove(operandStack.size() - 1);operandStack.remove(operandStack.size() - 1);operandStack.add(num1 / num2);}// 插入新的运算符operatorStack.add(operator);}} else if (i == record.length() - 1) {// 如果遍历到末尾,添加最后一个操作数try {operandStack.add(Double.parseDouble(record_string.substring(previousOperatorSubscript, record.length())));} catch (Exception e) {result.setText("错误");return;}// 如果上一个操作数是乘法或除法,则进行运算if (operatorStack.size() > 0) {String pre_operator = operatorStack.get(operatorStack.size() - 1);if ("×".equals(pre_operator)) {// 移除上一个运算符operatorStack.remove(operatorStack.size() - 1);Double num1 = operandStack.get(operandStack.size() - 2);Double num2 = operandStack.get(operandStack.size() - 1);operandStack.remove(operandStack.size() - 1);operandStack.remove(operandStack.size() - 1);operandStack.add(num1 * num2);} else if ("÷".equals(pre_operator)) {// 移除上一个运算符operatorStack.remove(operatorStack.size() - 1);Double num1 = operandStack.get(operandStack.size() - 2);Double num2 = operandStack.get(operandStack.size() - 1);operandStack.remove(operandStack.size() - 1);operandStack.remove(operandStack.size() - 1);operandStack.add(num1 / num2);}}}}// 判断两个栈是否合法if (operandStack.size() != operatorStack.size() + 1) {result.setText("错误");return;}// 完成剩余栈中的运算for (int i = 0; i < operatorStack.size(); i++) {String operator = operatorStack.get(i);if ("+".equals(operator)) {Double num1 = operandStack.get(0);Double num2 = operandStack.get(1);operandStack.remove(0);operandStack.remove(0);operandStack.add(0, num1 + num2);} else if ("-".equals(operator)) {Double num1 = operandStack.get(0);Double num2 = operandStack.get(1);operandStack.remove(0);operandStack.remove(0);operandStack.add(0, num1 - num2);} else if ("×".equals(operator)) {Double num1 = operandStack.get(0);Double num2 = operandStack.get(1);operandStack.remove(0);operandStack.remove(0);operandStack.add(0, num1 * num2);} else if ("÷".equals(operator)) {Double num1 = operandStack.get(0);Double num2 = operandStack.get(1);operandStack.remove(0);operandStack.remove(0);operandStack.add(0, num1 / num2);}}result.setText(String.valueOf(operandStack.get(0))); //将结果完整输出record.setText(String.valueOf(operandStack.get(0)));previousOperatorSubscript = 0;nextOperatorSubscript = 0;operandStack.clear();operatorStack.clear();break;default:break;}}}
}