Android计算器
目录
这是我第一个Android小项目,相信这也是大多数人的第一个小项目。
这个项目非常的简单,只有一个Activity。
首先是布局文件,这里我用的是线性布局。
计算器的布局
这个布局文件中的按钮(Button)比较多。
首先是一个TextView,然后是一堆按钮。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
>
<TextView
android:id="@+id/text_edit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:textColor="#e51c23"
android:gravity="bottom|right"
android:textSize="30sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/button_1line"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<Button
android:id="@+id/button_left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="("
android:textSize="30sp" />
<Button
android:id="@+id/button_right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text=")"
android:textSize="30sp" />
<Button
android:id="@+id/button_clear"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="-8dp"
android:layout_weight="1"
android:text="C"
android:textSize="30sp" />
<Button
android:id="@+id/button_back"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="-8dp"
android:layout_weight="1"
android:text="<Del"
android:textAllCaps="false"
android:textSize="25sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/button_2line"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<Button
android:id="@+id/button_7"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="7"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_8"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text="8"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_9"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text="9"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_add"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text="+"
android:textSize="40sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/button_3line"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<Button
android:id="@+id/button_4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="4"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="5"
android:layout_marginLeft="-8dp"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_6"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text="6"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_minus"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text="-"
android:textSize="50sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/button_4line"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<Button
android:id="@+id/button_1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="1"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text="2"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text="3"
android:textSize="30sp"
/>
<Button
android:id="@+id/button_mul"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-8dp"
android:text="×"
android:textSize="35sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/button_5line"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<Button
android:id="@+id/button_point"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="."
android:textSize="40sp" />
<Button
android:id="@+id/button_0"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="-8dp"
android:layout_weight="1"
android:text="0"
android:textSize="30sp" />
<Button
android:id="@+id/button_div"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="÷"
android:layout_marginLeft="-8dp"
android:textSize="40sp" />
<Button
android:id="@+id/button_equals"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="-5dp"
android:text="="
android:background="#3388FF"
android:textSize="50sp"
/>
</LinearLayout>
</LinearLayout>
接下来就是ManActivity中的代码了,当然其中主要就是一个按钮的监听,也没有什么难度。
MainActivity中的代码
package com.example.calculatortest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
StringBuffer sb = new StringBuffer();
private TextView text = null; // 用于显示输入和输出
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_1);
getSupportActionBar().hide();
text = (TextView) findViewById(R.id.text_edit);
// 数字按钮
Button button0 = (Button)findViewById(R.id.button_0);
Button button1 = (Button)findViewById(R.id.button_1);
Button button2 = (Button)findViewById(R.id.button_2);
Button button3 = (Button)findViewById(R.id.button_3);
Button button4 = (Button)findViewById(R.id.button_4);
Button button5 = (Button)findViewById(R.id.button_5);
Button button6 = (Button)findViewById(R.id.button_6);
Button button7 = (Button)findViewById(R.id.button_7);
Button button8 = (Button)findViewById(R.id.button_8);
Button button9 = (Button)findViewById(R.id.button_9);
// 功能按钮
// 四则运算
Button button_div = (Button)findViewById(R.id.button_div);
Button button_mul = (Button)findViewById(R.id.button_mul);
Button button_add = (Button)findViewById(R.id.button_add);
Button button_minus = (Button) findViewById(R.id.button_minus);
Button button_back = (Button)findViewById(R.id.button_back);
Button button_clear = (Button) findViewById(R.id.button_clear);
Button button_point = (Button) findViewById(R.id.button_point);
Button button_equals = (Button) findViewById(R.id.button_equals);
// 左右括号
Button button_left = (Button) findViewById(R.id.button_left);
Button button_right = (Button) findViewById(R.id.button_right);
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_minus.setOnClickListener(this);
button_mul.setOnClickListener(this);
button_div.setOnClickListener(this);
button_back.setOnClickListener(this);
button_clear.setOnClickListener(this);
button_point.setOnClickListener(this);
button_equals.setOnClickListener(this);
button_left.setOnClickListener(this);
button_right.setOnClickListener(this);
}
private String sign = "+-*/";
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button_1:
sb.append("1");
text.setText(sb);
break;
case R.id.button_2:
sb.append("2");
text.setText(sb);
break;
case R.id.button_3:
sb.append("3");
text.setText(sb);
break;
case R.id.button_4:
sb.append("4");
text.setText(sb);
break;
case R.id.button_5:
sb.append("5");
text.setText(sb);
break;
case R.id.button_6:
sb.append("6");
text.setText(sb);
break;
case R.id.button_7:
sb.append("7");
text.setText(sb);
break;
case R.id.button_8:
sb.append("8");
text.setText(sb.toString());
break;
case R.id.button_9:
sb.append("9");
text.setText(sb);
break;
case R.id.button_0:
sb.append("0");
text.setText(sb);
break;
case R.id.button_back:
if(sb.length() > ) {
sb.deleteCharAt(sb.length() - );
text.setText(sb);
}
break;
case R.id.button_clear:
sb.setLength();
text.setText(sb);
break;
case R.id.button_add:
if(sb.length() > && sign.indexOf(sb.charAt(sb.length() - )) == -) {
sb.append("+");
}
text.setText(sb);
break;
case R.id.button_minus:
if(sb.length() == || sb.length() > && sign.indexOf(sb.charAt(sb.length() - )) == -) {
sb.append("-");
}
text.setText(sb);
break;
case R.id.button_mul:
if(sb.length() > && sign.indexOf(sb.charAt(sb.length() - )) == -) {
sb.append("×");
}
text.setText(sb);
break;
case R.id.button_div:
if(sb.length() > && sign.indexOf(sb.charAt(sb.length() - )) == -) {
sb.append("÷");
}
text.setText(sb);
break;
case R.id.button_point:
if(sb.length() == ||!Character.isDigit(sb.charAt(sb.length() - ))) {
sb.append("0.");
}
else {
sb.append(".");
}
text.setText(sb);
break;
case R.id.button_left:
sb.append("(");
text.setText(sb);
break;
case R.id.button_right:
if (sb.indexOf("(") != -) {
sb.append(")");
}
text.setText(sb);
break;
case R.id.button_equals:
String s = sb.toString().replace("×", "*").replace("÷", "/");
try {
s = Calculator.toSuffix(s);
} catch (Exception ex) {
s = "出错";
}
text.setText(sb + "\n"+"=" + s);
if (s != "出错") {
sb = new StringBuffer(s);
}else {
sb.delete(, sb.length());
}
break;
}
}
}
当然还有一个Calculator类,这个就是计算的核心代码了,这个类中用的是中缀转后缀来计算的,当然如果看不懂,可以看我的这个博客:
package com.example.calculatortest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayDeque;
public class Calculator {
public static String toSuffix(String input) {
int len = input.length();
char c, tempChar;
ArrayDeque<Character> s1 = new ArrayDeque<Character>();
ArrayDeque<BigDecimal> s2 = new ArrayDeque<>();
int lastIndex = -;
for (int i = ; i < len; ++i) {
c = input.charAt(i);
if (Character.isDigit(c) || c == '.') {
lastIndex = readDouble(input, i);
if (lastIndex == -)
return "出错";
BigDecimal number = new BigDecimal(input.substring(i, lastIndex));
s2.push(number);
i = lastIndex - ;
}else if (c == '-' && i == ) {
lastIndex = readDouble(input, i + );
if (lastIndex == -)
return "出错";
BigDecimal number = new BigDecimal(input.substring(i, lastIndex));
s2.push(number);
i = lastIndex - ;
}else if (i > && c == '-' &&
(input.charAt(i-) == '('
|| isOperator(input.charAt(i-)))) {
lastIndex = readDouble(input, i + );
if (lastIndex == -)
return "出错";
BigDecimal number = new BigDecimal(input.substring(i, lastIndex));
s2.push(number);
i = lastIndex - ;
}
else if (isOperator(c)) {
while (!s1.isEmpty() && s1.peek() != '('
&& priorityCompare(c, s1.peek()) <= ) {
// double num1 = s2.pop();
// double num2 = s2.pop();
BigDecimal num1 = s2.pop();
BigDecimal num2 = s2.pop();
s2.push(calc(num2, num1, s1.pop()));
}
s1.push(c);
} else if (c == '(') {
s1.push(c);
} else if (c == ')') {
while ((tempChar = s1.pop()) != '(') {
// double num1 = s2.pop();
// double num2 = s2.pop();
BigDecimal num1 = s2.pop();
BigDecimal num2 = s2.pop();
s2.push(calc(num2, num1, tempChar));
if (s1.isEmpty()) {
return "出错";
}
}
} else if (c == ' ') {
// ignore
} else {
return "出错";
}
}
while (!s1.isEmpty()) {
tempChar = s1.pop();
// double num1 = s2.pop();
// double num2 = s2.pop();
BigDecimal num1 = s2.pop();
BigDecimal num2 = s2.pop();
s2.push(calc(num2, num1, tempChar));
}
BigDecimal result = s2.pop();
if (!s2.isEmpty())
return "出错";
if (result.toString().length() < )
return result.stripTrailingZeros().toPlainString();
else
return result.round(new MathContext(, RoundingMode.HALF_UP)).toEngineeringString();
}
/**
* 获取是double值得最后一位索引
*/
public static int readDouble(String str, int start)
throws IllegalArgumentException{
int len = str.length();
int dotIndex = -;
char ch;
for (int i = start; i < len ; i++) {
ch = str.charAt(i);
if(ch == '.') {
if(dotIndex != -)
return -;
else if(i == len - )
return -;
else
dotIndex = i;
} else if(!Character.isDigit(ch)) {
if (dotIndex == - || i - dotIndex > )
return i;
else
throw new IllegalArgumentException("不是数字,不能作为数字的一部分");
}
else if(i == len - ) {
return len;
}
}
return -;
}
/**
* 判断优先级
*/
private static int priorityCompare (char op1, char op2) {
if(op1 == '+' || op1 == '-')
return (op2 == '*' || op2 == '/' ? - : );
if (op1 == '*' || op1 == '/') {
return (op2 == '+' || op2 == '-' ? : );
}
return ;
}
/**
* 这个函数能够判断是否是操作运算符
*/
private static boolean isOperator (char ch) {
return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
}
/**
* 计算两个数的结果
* 并返回
*/
private static BigDecimal calc (BigDecimal num1, BigDecimal num2, char op)
throws IllegalArgumentException{
switch (op) {
case '+':
return num1.add(num2);
case '-':
return num1.subtract(num2);
case '*':
return num1.multiply(num2);
case '/':
if (num2.equals())
throw new IllegalArgumentException("除数不能为0");
return num1.divide(num2, , RoundingMode.HALF_UP);
default:
return new BigDecimal();
}
}
}