计算器可实现±*/负号以及括号的运算
主要用到中缀转后缀,可以先了解一下中缀转后缀的思想,再进行计算器的实现
计算器的布局如图:
布局使用的是LinerLayout的嵌套,可以模仿自己手机的计算器布局。
设置输入为一行,可进行字体自动缩小,不过没有光标的移动,未设置最多输入位数
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/edit_text"
app:autoSizeMaxTextSize = "80sp"
app:autoSizeMinTextSize = "20sp"
app:autoSizeStepGranularity= "3sp"
app:autoSizeTextType = "uniform"
android:layout_width="match_parent"
android:maxLines="1"
android:layout_height="200dp"
android:background="#FFFFFF"
android:gravity="right|bottom"
android:editable="false"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<Button
android:id="@+id/button_c"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="c"
android:textColor="#63B8FF"
android:textSize="30sp"
android:background="@drawable/ev_shape"
/>
<Button
android:id="@+id/button_div"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="÷"
android:textColor="#63B8FF"
android:textSize="30sp"
android:background="@drawable/ev_shape"
/>
<Button
android:id="@+id/button_mul"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="×"
android:textColor="#63B8FF"
android:textSize="30sp"
android:background="@drawable/ev_shape"
/>
<Button
android:id="@+id/button_delete"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="d"
android:textColor="#63B8FF"
android:textSize="30sp"
android:background="@drawable/ev_shape"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<Button
android:id="@+id/button_7"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="7"
android:textSize="30sp"
android:background="@drawable/ev_shape1"
/>
<Button
android:id="@+id/button_8"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="8"
android:textAllCaps="false"
android:textSize="30sp"
android:background="@drawable/ev_shape1"
/>
<Button
android:id="@+id/button_9"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="9"
android:textAllCaps="false"
android:textSize="30sp"
android:background="@drawable/ev_shape1"
/>
<Button
android:id="@+id/button_sub"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="-"
android:textColor="#63B8FF"
android:textSize="30sp"
android:background="@drawable/ev_shape"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<Button
android:id="@+id/button_4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="4"
android:textSize="30sp"
android:background="@drawable/ev_shape1"
/>
<Button
android:id="@+id/button_5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="5"
android:textAllCaps="false"
android:textSize="30sp"
android:background="@drawable/ev_shape1"
/>
<Button
android:id="@+id/button_6"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="6"
android:textAllCaps="false"
android:textSize="30sp"
android:background="@drawable/ev_shape1"
/>
<Button
android:id="@+id/button_sum"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="+"
android:textColor="#63B8FF"
android:textSize="30sp"
android:background="@drawable/ev_shape"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<Button
android:id="@+id/button_1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="1"
android:textSize="30sp"
android:background="@drawable/ev_shape1"/>
<Button
android:id="@+id/button_2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/ev_shape1"
android:gravity="center"
android:text="2"
android:textAllCaps="false"
android:textSize="30sp" />
<Button
android:id="@+id/button_3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/ev_shape1"
android:gravity="center"
android:text="3"
android:textAllCaps="false"
android:textSize="30sp" />
<Button
android:id="@+id/button_point"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/ev_shape"
android:gravity="center"
android:text="."
android:textColor="#63B8FF"
android:textAllCaps="false"
android:textSize="30sp" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<Button
android:id="@+id/button_0"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/ev_shape1"
android:gravity="center"
android:text="0"
android:textSize="30sp" />
<Button
android:id="@+id/left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/ev_shape1"
android:gravity="center"
android:text="("
android:textSize="30sp" />
<Button
android:id="@+id/right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text=")"
android:textSize="30sp"
android:background="@drawable/ev_shape1"//自定义布局
/>
<Button
android:id="@+id/equ"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#4F94CD"
android:text="="
android:gravity="center"
android:textColor="#63B8FF"
android:textSize="30sp" />
</LinearLayout>
</LinearLayout>
里面涉及的自定义布局在project中的app->src->main->rec->drawable中
ev_shape
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#F0F0F0"/>//内部填充颜色
<stroke android:width="1dip"
android:color="#F5F5F5" />//轮廓颜色
</shape>
ev_shape1
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#FFFFFF"/>
<stroke android:width="1dip"
android:color="#F5F5F5" />
</shape>
主活动中:
private TextView editText;
private int flag = 1;
private String result;
private boolean flag1 = false;
private StringBuilder add = new StringBuilder();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null) {
actionBar.hide();
}
//获取布局中定义的元素
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 buttonDele = (Button) findViewById(R.id.button_delete);
Button buttonDiv = (Button) findViewById(R.id.button_div);
Button buttonEqu = (Button) findViewById(R.id.equ);
Button buttonC = (Button) findViewById(R.id.button_c);
Button buttonMul = (Button) findViewById(R.id.button_mul);
Button buttonSum = (Button) findViewById(R.id.button_sum);
Button buttonSub = (Button) findViewById(R.id.button_sub);
Button buttonPoint = (Button) findViewById(R.id.button_point);
Button left = (Button) findViewById(R.id.left);
Button right = (Button) findViewById(R.id.right);
editText = (TextView) findViewById(R.id.edit_text
//为按钮注册监听器
buttonPoint.setOnClickListener(this);
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);
left.setOnClickListener(this);
right.setOnClickListener(this);
buttonDiv.setOnClickListener(this);
buttonDele.setOnClickListener(this);
buttonC.setOnClickListener(this);
buttonMul.setOnClickListener(this);
buttonSum.setOnClickListener(this);
buttonSub.setOnClickListener(this);
buttonEqu.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int last = 0;
if(add.length() != 0) {
last = add.codePointAt(add.length()-1);
}
//不能无限的输入0
if(add.length() == 1 && add.charAt(0) == '0') {
add.deleteCharAt(0);
}
switch (view.getId()) {
case R.id.button_0:
if(flag1) {//第一次计算出结果,当点击数字时,进行新的运算
add.delete(0,add.length());
flag1 = false;
add = add.append("0");
}else if(flag1() == ')') {
add = add.append("*0");//将(表达式)0转成为(表达式)*0进行计算,下面类似
}else{
add = add.append("0");
}
editText.setText(add);
break;
case R.id.button_1:
if(flag1) {
add.delete(0,add.length());
flag1 = false;
add = add.append("1");
}else if(flag1() == ')') {
add = add.append("*1");
}else{
add = add.append("1");
}
editText.setText(add);
break;
case R.id.button_2:
if(flag1) {//
add.delete(0,add.length());
flag1 = false;
add = add.append("2");
}else if(flag1() == ')') {
add = add.append("*2");
}else{
add = add.append("2");
}
editText.setText(add);
break;
case R.id.button_3:
if(flag1) {
add.delete(0,add.length());
flag1 = false;
add = add.append("3");
}else if(flag1() == ')') {
add = add.append("*3");
}else{
add = add.append("3");
}
editText.setText(add);
break;
case R.id.button_4:
if(flag1) {
add.delete(0,add.length());
flag1 = false;
add = add.append("4");
}else if(flag1() == ')') {
add = add.append("*4");
}else{
add = add.append("4");
}
editText.setText(add);
break;
case R.id.button_5:
if(flag1) {
add.delete(0,add.length());
flag1 = false;
add = add.append("5");
}else if(flag1() == ')') {
add = add.append("*5");
}else{
add = add.append("5");
}
editText.setText(add);
break;
case R.id.button_6:
if(flag1) {
add.delete(0,add.length());
flag1 = false;
add = add.append("6");
}else if(flag1() == ')') {
add = add.append("*6");
}else{
add = add.append("6");
}
editText.setText(add);
break;
case R.id.button_7:
if(flag1) {
add.delete(0,add.length());
flag1 = false;
add = add.append("7");
}else if(flag1() == ')') {
add = add.append("*7");
}else{
add = add.append("7");
}
editText.setText(add);
break;
case R.id.button_8:
if(flag1) {
add.delete(0,add.length());
flag1 = false;
add = add.append("8");
}else if(flag1() == ')') {
add = add.append("*8");
}else{
add = add.append("8");
}
editText.setText(add);
break;
case R.id.button_9:
if(flag1) {
add.delete(0,add.length());
flag1 = false;
add = add.append("9");
}else if(flag1() == ')') {
add = add.append("*9");
}else{
add = add.append("9");
}
editText.setText(add);
break;
case R.id.button_sub:
if(flag1) {//当第一次计算出结果,点击运算符则保存第一次计算的结果。
flag1 = false;
}
if(Character.isDigit(flag1()) || flag1() == ')' || flag1() == '('|| flag1() == '+' || flag1() == '*' || flag1() == '/' || flag1() == '.' || add.length() == 0){
add = add.append("-");
flag = 1;
editText.setText(add);
}
break;
case R.id.left:
if(flag1) {
add.delete(0, add.length());
flag1 = false;
add = add.append("(");
editText.setText(add);
}else if((add.length() >1 && last <= '0' && last >= '9' || last != '(' || last == '(' )&& flag1() == '-'){//(前面为-时转化为-1*(计算
add.insert(add.length() - 1,"-1*(");
add.delete(add.length() - 1,add.length());
editText.setText(add);
} else if(Character.isDigit(flag1())){//当(前面为数字,则转化为 数字*(
add = add.append("*(");
editText.setText(add);
}else if( last <= '0' && last >= '9' || last != '(' || last == '(') {
add = add.append("(");
editText.setText(add);
}
break;
case R.id.right:
if((last >= '0' && last <= '9' || last == ')') && flag2() == 1) {
add = add.append(")");
editText.setText(add);
}
break;
case R.id.button_div:
if(flag1) {
flag1 = false;
}
if (Character.isDigit(flag1()) || flag1() == ')' || flag1() == '.') {
add = add.append("/");
flag = 1;
}
if(add.length() == 0) {
add.append("0/");
}
editText.setText(add);
break;
case R.id.button_sum:
if(flag1) {
flag1 = false;
}
if(Character.isDigit(flag1()) || flag1() == ')' || flag1() == '.'){
add = add.append("+");
flag = 1;
editText.setText(add);
}
if(add.length() == 0) {
add.append("0+");
editText.setText(add);
}
break;
case R.id.button_mul:
if(flag1) {
flag1 = false;
}
if (Character.isDigit(flag1()) || flag1() == ')' || flag1() == '.') {
add = add.append("*");
flag = 1;
}
if(add.length() == 0) {
add.append("0*");
}
editText.setText(add);
break;
case R.id.button_delete:
if (add.length() != 0) {
flag = 1;
add.delete(add.length() - 1, add.length());
editText.setText(add);
}
break;
case R.id.button_point:
//下面一系列判断,限制小数点的输入
char ch;
if(add.length() == 0) {
ch = '$';
}
else{
ch = add.charAt(add.length() - 1);
}
if(flag1) {
add.delete(0,add.length());
flag1 = false;
}
if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || add.length() == 0) {
add.append("0.");
flag = 0;
editText.setText(add);
}else if(ch != '.' && flag == 1 && flag1() != ')') {
add = add.append(".");
flag = 0;
editText.setText(add);
}else if(ch == ')') {
add.append("*0.");
editText.setText(add);
}
break;
case R.id.button_c:
flag = 1;
add.delete(0,add.length());
editText.setText(add);
break;
case R.id.equ:
if(add.length() > 1) {
//自动进行括号匹配
try{
while(flag2() != 0) {
add.append(")");
}
Result r = new Result();
String a = r.getString(add);
result = r.getResult(a);
editText.setText(result);
add = add.delete(0,add.length());
if(Character.isDigit(result.charAt(0)) || Character.isDigit(result.charAt(1))) {
flag1 = true;
add = add.append(result);
}
}catch (Exception e) {
result = "错误";
editText.setText(result);
}
}
break;
default:
break;
}
}
public char flag1() {//获取当前显示的最新的字符
char ch;
if(add.length() >= 1) {
ch = add.charAt(add.length() - 1);
}else {
ch = '&';
}
return ch;
}
//对左右括号进行计数,可进行括号的匹配
public int flag2() {
int a = 0;
int b = 0;
for(int i = 0; i < add.length(); i++) {
if(add.charAt(i) == '(') {
a++;
}
if(add.charAt(i) == ')') {
b++;
}
}
if(a == b)
return 0;
if(a > b)
return 1;
return 2;
}
}
中缀转后缀及计算
class Result {
public String getString(StringBuilder add) {
HashMap<Character,Integer> hm = new HashMap<>();
//判断优先级
hm.put('(',0);
hm.put('+',1);
hm.put('-',1);
hm.put('*',2);
hm.put('/',2);
ArrayList<String> al = new ArrayList<>();
ArrayList<Character> stack = new ArrayList<>();
char[] arr = add.substring(0, add.length()).toCharArray();
String show = "+-*/()";
char ch;
int len = 0;
//下面都是中缀转后缀的实现,当栈定的运算符优先级大于即将入栈的运算符,
//则栈内的运算符全部出栈
for (int i = 0; i < arr.length; i++) {
ch = arr[i];
if(ch == '-' && i == 0 ) {
al.add("0");
}
if (Character.isDigit(ch)) {
++ len;
} else if (ch == '.') {
++ len;
}
else if(ch == '-' && i != 0 && show.indexOf(arr[i - 1])!= -1 && arr[i - 1] != ')') {
++ len;
}else if (show.indexOf(ch) != -1) {
if (len > 0) {
al.add(String.valueOf(Arrays.copyOfRange(arr, i - len, i)));
len = 0;
}
if(ch == '(') {
stack.add(ch);
continue;
}
if(!stack.isEmpty()) {
int size = stack.size() - 1;
boolean flag = false;
while (size >= 0 && ch == ')' && stack.get(size) != '(') {
al.add(String.valueOf(stack.remove(size)));//获取数字
size --;//保证一直指向栈顶元素
flag = true;
}
if(ch == ')' && stack.get(size) == '(') {
flag = true;
}
while(size >= 0 && !flag && hm.get(stack.get(size)) >= hm.get(ch)) {
al.add(String.valueOf(stack.remove(size)));
size --;
}
}
if(ch != ')') {
stack.add(ch);
}else{
stack.remove(stack.size() - 1);//'('出栈
}
}
if(i == arr.length - 1) {
if(len > 0) {
al.add(String.valueOf(Arrays.copyOfRange(arr, i - len+1, i+1)));
}
int size = stack.size() - 1;
while(size >= 0) {
al.add(String.valueOf(stack.remove(size)));
size --;
}
}
}
String a = al.toString();
return a.substring(1,a.length() - 1);
}
//后缀表达式的计算
public String getResult(String string) {
String[] arr = string.split(",");
ArrayList<String> list = new ArrayList<>();
for(int i = 0;i < arr.length; i++) {
int size = list.size();
switch (arr[i]) {
case " -" :
BigDecimal a = new BigDecimal(list.remove(size - 2)).subtract(new BigDecimal(list.remove(size - 2)));
list.add(a.toString());
break;
case " +" :
BigDecimal b = new BigDecimal(list.remove(size - 2)).add(new BigDecimal(list.remove(size - 2)));
list.add(b.toString());
break;
case " *" :
BigDecimal c = new BigDecimal(list.remove(size - 2)).multiply(new BigDecimal(list.remove(size - 2)));
list.add(c.toString());
break;
case " /" :
BigDecimal d = new BigDecimal(list.remove(size - 2));
BigDecimal d1 = new BigDecimal(list.remove(size - 2));
list.add(String.valueOf(d.divide(d1,9, BigDecimal.ROUND_HALF_UP).doubleValue()));
break;
default:
list.add(arr[i].trim());
break;
}
}
String line;
//数字/0位Infinity,报错
if(list.size() == 1 && list.get(0) != "Infinity") {
line = list.get(0);
}else{
line = "错误";
}
return line;
}
}
可以改计算器app的图标
换的图片放在 Project下的app->src->main->res->drawable
打开 AndroidMainfest.xml
android:allowBackup="true"
android:icon="@drawable/my"//要换的图标
android:label="suager"//app的名字
android:supportsRtl="true"
android:theme="@style/AppTheme">