您好,登錄后才能下訂單哦!
今天小編給大家分享一下Android如何實現計算器功能的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
頁面效果
布局代碼
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="8"> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:id="@+id/text_view" android:layout_weight="2" android:textSize="70dp" android:gravity="right|bottom" android:maxLines="2" /> <TextView android:id="@+id/result_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:gravity="right|bottom" android:maxLines="1" android:textSize="65dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal" android:weightSum="5"> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_ac" android:layout_weight="1" android:text="AC" android:background="#ff0000" android:textColor="#000" android:textSize="20dp" android:layout_margin="5dp" /> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_left" android:layout_weight="1" android:text="(" android:background="#fff" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_right" android:layout_weight="1" android:text=")" android:background="#fff" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_divide" android:layout_weight="1" android:text="/" android:background="#fffaf0" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_del" android:layout_weight="1" android:text="DEL" android:background="#808a87" android:textColor="#000" android:textSize="15dp" android:layout_margin="5dp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal" android:weightSum="4"> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_7" android:layout_weight="1" android:text="7" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_8" android:layout_weight="1" android:text="8" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_9" android:layout_weight="1" android:text="9" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_mult" android:layout_weight="1" android:text="*" android:background="#fffaf0" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal" android:weightSum="4"> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_4" android:layout_weight="1" android:text="4" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_5" android:layout_weight="1" android:text="5" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_6" android:layout_weight="1" android:text="6" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_add" android:layout_weight="1" android:text="+" android:background="#fffaf0" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal" android:weightSum="4"> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_1" android:layout_weight="1" android:text="1" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_2" android:layout_weight="1" android:text="2" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_3" android:layout_weight="1" android:text="3" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_minus" android:layout_weight="1" android:text="-" android:background="#fffaf0" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal" android:weightSum="4"> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_0" android:layout_weight="2" android:text="0" android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_dot" android:layout_weight="1" android:text="." android:textColor="#000" android:textSize="30dp" android:layout_margin="5dp"/> <Button android:layout_width="0dp" android:layout_height="match_parent" android:id="@+id/button_result" android:layout_weight="1" android:text="=" android:background="#ff6347" android:textColor="#fff" android:textSize="30dp" android:layout_margin="5dp"/> </LinearLayout> </LinearLayout>
解析
1、布局使用LinearLayout布局,android:orientation="vertical"指定垂直布局,從上至下依次是表達式顯示框,結果顯示框以及五行按鈕,并指定總權重方便控制顯示。
2、文本框TextView使用android:gravity="right|bottom"指定其從右下開始顯示內容。
3、在按鈕上,使用android:background="#ff0000"指定按鈕背景顏色,使用android:layout_margin="5dp"控制偏移,使其不會過于緊湊。(關于按鈕背景顏色無法設置,可在res//values//themes.xml文件下將代碼<style name="Theme.Calculation" parent="Theme.MaterialComponents.DayNight.DarkActionBar.">
改為<style name="Theme.Calculation" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge">)
代碼部分
package com.example.calculation; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.util.TypedValue; import android.view.View; import android.widget.Button; import android.widget.TextView; import java.math.BigDecimal; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private final StringBuilder sb = new StringBuilder();//用于表達式的輸入 private String expression = "";//最終表達式的確定 private String result = "";//計算結果 private boolean isHasDot = false;//是否有小數點 private final Stack<Boolean> dotStack = new Stack<>(); //用棧存儲每一個數字是否有小數點 private boolean isZero = false;//是否是數字零 private final Stack<Boolean> zeroStack = new Stack<>(); private int leftNum = 0;//左括號數量 private int rightNum = 0;//右括號數量 private TextView textView; private TextView result_view; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.text_view); textView.setAutoSizeTextTypeUniformWithConfiguration(4, 70, 10, TypedValue.COMPLEX_UNIT_DIP); //將顯示框設置為根據行數自動縮小 result_view = (TextView) findViewById(R.id.result_view); result_view.setAutoSizeTextTypeUniformWithConfiguration(4, 70, 10, TypedValue.COMPLEX_UNIT_DIP); Button button1 = (Button) findViewById(R.id.button_1); button1.setOnClickListener(this); Button button2 = (Button) findViewById(R.id.button_2); button2.setOnClickListener(this); Button button3 = (Button) findViewById(R.id.button_3); button3.setOnClickListener(this); Button button4 = (Button) findViewById(R.id.button_4); button4.setOnClickListener(this); Button button5 = (Button) findViewById(R.id.button_5); button5.setOnClickListener(this); Button button6 = (Button) findViewById(R.id.button_6); button6.setOnClickListener(this); Button button7 = (Button) findViewById(R.id.button_7); button7.setOnClickListener(this); Button button8 = (Button) findViewById(R.id.button_8); button8.setOnClickListener(this); Button button9 = (Button) findViewById(R.id.button_9); button9.setOnClickListener(this); Button button0 = (Button) findViewById(R.id.button_0); button0.setOnClickListener(this); Button buttondot = (Button) findViewById(R.id.button_dot); buttondot.setOnClickListener(this); Button buttonadd = (Button) findViewById(R.id.button_add); buttonadd.setOnClickListener(this); Button buttonminus = (Button) findViewById(R.id.button_minus); buttonminus.setOnClickListener(this); Button buttonmult = (Button) findViewById(R.id.button_mult); buttonmult.setOnClickListener(this); Button buttondivide = (Button) findViewById(R.id.button_divide); buttondivide.setOnClickListener(this); Button buttonac = (Button) findViewById(R.id.button_ac); buttonac.setOnClickListener(this); Button buttondel = (Button) findViewById(R.id.button_del); buttondel.setOnClickListener(this); Button buttonleft = (Button) findViewById(R.id.button_left); buttonleft.setOnClickListener(this); Button buttonright = (Button) findViewById(R.id.button_right); buttonright.setOnClickListener(this); Button buttonresult = (Button) findViewById(R.id.button_result); buttonresult.setOnClickListener(this); } @Override public void onClick(View v) { result_view.setText(""); switch (v.getId()) { case R.id.button_1: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('1'); textView.setText(sb.toString()); break; case R.id.button_2: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('2'); textView.setText(sb.toString()); break; case R.id.button_3: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('3'); textView.setText(sb.toString()); break; case R.id.button_4: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('4'); textView.setText(sb.toString()); break; case R.id.button_5: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('5'); textView.setText(sb.toString()); break; case R.id.button_6: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('6'); textView.setText(sb.toString()); break; case R.id.button_7: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('7'); textView.setText(sb.toString()); break; case R.id.button_8: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('8'); textView.setText(sb.toString()); break; case R.id.button_9: if (isZero == true) { sb.deleteCharAt(sb.length() - 1); isZero = false; } sb.append('9'); textView.setText(sb.toString()); break; case R.id.button_0: if (isZero == false) { sb.append('0'); if (sb.length() == 1 || !('0' <= sb.charAt(sb.length() - 2) && sb.charAt(sb.length() - 2) <= '9') && sb.charAt(sb.length() - 2) != '.') { isZero = true; } } textView.setText(sb.toString()); break; case R.id.button_dot: if (isHasDot == false) { if (sb.length() == 0 || !('0' <= sb.charAt(sb.length() - 1) && sb.charAt(sb.length() - 1) <= '9')) { sb.append("0."); } else { sb.append('.'); } isHasDot = true; isZero = false; } textView.setText(sb.toString()); break; case R.id.button_add: if (sb.length() != 0 && (sb.charAt(sb.length() - 1) == '+' || sb.charAt(sb.length() - 1) == '-' || sb.charAt(sb.length() - 1) == '*' || sb.charAt(sb.length() - 1) == '/')) { sb.setCharAt(sb.length() - 1, '+'); } else if (sb.length() != 0) { sb.append('+'); zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; } if (result.matches("[-]?\\d+[.]?\\d*") && sb.length() == 0) { sb.append(result + "+"); isHasDot = result.matches("[-]?\\d*[.]\\d*"); isZero = "0".equals(result); zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; } textView.setText(sb.toString()); break; case R.id.button_minus: if (sb.length() != 0 && (sb.charAt(sb.length() - 1) == '+' || sb.charAt(sb.length() - 1) == '-' || sb.charAt(sb.length() - 1) == '*' || sb.charAt(sb.length() - 1) == '/')) { sb.append('('); zeroStack.push(isZero); dotStack.push(isHasDot); leftNum++; } if (result.matches("[-]?\\d+[.]?\\d*") && sb.length() == 0) { sb.append(result + "-"); isHasDot = result.matches("[-]?\\d*[.]\\d*"); isZero = "0".equals(result); zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; } sb.append('-'); zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; textView.setText(sb.toString()); break; case R.id.button_mult: if (sb.length() != 0 && (sb.charAt(sb.length() - 1) == '+' || sb.charAt(sb.length() - 1) == '-' || sb.charAt(sb.length() - 1) == '*' || sb.charAt(sb.length() - 1) == '/')) { sb.setCharAt(sb.length() - 1, '*'); } else if (sb.length() != 0) { sb.append('*'); zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; } if (result.matches("[-]?\\d+[.]?\\d*") && sb.length() == 0) { sb.append(result + "*"); isHasDot = result.matches("[-]?\\d*[.]\\d*"); isZero = "0".equals(result); zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; } textView.setText(sb.toString()); break; case R.id.button_divide: if (sb.length() != 0 && (sb.charAt(sb.length() - 1) == '+' || sb.charAt(sb.length() - 1) == '-' || sb.charAt(sb.length() - 1) == '*' || sb.charAt(sb.length() - 1) == '/')) { sb.setCharAt(sb.length() - 1, '/'); } else if (sb.length() != 0) { sb.append('/'); zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; } if (result.matches("[-]?\\d+[.]?\\d*") && sb.length() == 0) { sb.append(result + "/"); isHasDot = result.matches("[-]?\\d*[.]\\d*"); isZero = "0".equals(result); zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; } textView.setText(sb.toString()); break; case R.id.button_left: sb.append('('); leftNum++; zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; textView.setText(sb.toString()); break; case R.id.button_right: sb.append(')'); rightNum++; zeroStack.push(isZero); dotStack.push(isHasDot); isZero = false; isHasDot = false; textView.setText(sb.toString()); break; case R.id.button_del: if (sb.length() != 0) { if (sb.charAt(sb.length() - 1) == '.') { isHasDot = false; if (sb.charAt(sb.length() - 2) == '0') { sb.deleteCharAt(sb.length() - 1); } } if (sb.charAt(sb.length() - 1) == '(') { leftNum--; } if (sb.charAt(sb.length() - 1) == ')') { rightNum--; } if (sb.charAt(sb.length() - 1) == '0' && isZero == true) { isZero = false; } if (!(sb.charAt(sb.length() - 1) == '.' || '0' <= sb.charAt(sb.length() - 1) && sb.charAt(sb.length() - 1) <= '9')) { if (!dotStack.isEmpty()) { isHasDot = dotStack.pop(); } if (!zeroStack.isEmpty()) { isZero = zeroStack.pop(); } } sb.deleteCharAt(sb.length() - 1); } result_view.setText(""); textView.setText(sb.toString()); break; case R.id.button_ac: if (sb.length() != 0) { sb.delete(0, sb.length()); } isHasDot = false; isZero = false; zeroStack.clear(); dotStack.clear(); expression = ""; result = ""; leftNum = 0; rightNum = 0; result_view.setText(""); textView.setText(""); break; case R.id.button_result: if (sb.length() != 0) { textView.setText(sb.toString()); isHasDot = false; isZero = false; zeroStack.clear(); dotStack.clear(); if (leftNum < rightNum) { result = "出錯"; sb.delete(0, sb.length()); result_view.setText(result); leftNum = 0; rightNum = 0; break; } else if (leftNum > rightNum) { while (leftNum > rightNum) { sb.append(')'); rightNum++; } } if (sb.charAt(0) == '-') { sb.insert(0, '0'); } if (sb.charAt(sb.length() - 1) == '+' || sb.charAt(sb.length() - 1) == '-') { sb.append('0'); } if (sb.charAt(sb.length() - 1) == '*' || sb.charAt(sb.length() - 1) == '/') { sb.append('1'); } for (int i = 1; i < sb.length() - 1; i++) { char ch = sb.charAt(i); if (ch == '(' && (sb.charAt(i - 1) == '.' || '0' <= sb.charAt(i - 1) && sb.charAt(i - 1) <= '9')) { sb.insert(i, '*'); } if (ch == ')' && '0' <= sb.charAt(i + 1) && sb.charAt(i + 1) <= '9') { sb.insert(i + 1, '*'); } } expression = sb.toString(); sb.delete(0, sb.length()); exchange(expression); expression = ""; leftNum = 0; rightNum = 0; } result_view.setText(result); break; } } public void exchange(String expression) { Queue<Object> queue = new LinkedList<>(); Stack<Character> stack = new Stack<>(); int figureNum = 0; int operatorNum = 0; StringBuilder numSb = new StringBuilder(); for (int i = 0; i < expression.length(); i++) { char ch = expression.charAt(i); if (ch == '.' || ('0' <= ch && ch <= '9')) { numSb.append(ch); } else { if (numSb.length() != 0) { queue.offer(new BigDecimal(numSb.toString())); figureNum++; numSb.delete(0, numSb.length()); } if (ch == '-' && expression.charAt(i - 1) == '(' && ('0' <= expression.charAt(i + 1) && expression.charAt(i + 1) <= '9')) { numSb.append(ch); continue; } if (ch == '(') { stack.push(ch); } else if ((ch == '+' || ch == '-') && !stack.isEmpty() && stack.peek() == '(') { stack.push(ch); } else if ((ch == '*' || ch == '/') && !stack.isEmpty() && !(stack.peek() == '*' || stack.peek() == '/')) { stack.push(ch); } else { while (!stack.empty() && stack.peek() != '(') { queue.offer(stack.pop()); operatorNum++; } if (!stack.isEmpty()) { stack.pop(); } if (ch != ')') { stack.push(ch); } } } } if (numSb.length() != 0) { queue.offer(new BigDecimal(numSb.toString())); figureNum++; } while (!stack.empty()) { queue.offer(stack.pop()); operatorNum++; } if (figureNum == operatorNum + 1) { calculate(queue); } else { result = "出錯"; } } public void calculate(Queue<Object> queue) { Stack<BigDecimal> stack = new Stack<>(); while (!queue.isEmpty()) { Object obj = queue.poll(); if (obj.getClass() == Character.class) { char operator = (Character) obj; BigDecimal num1 = (BigDecimal) stack.pop(); BigDecimal num2 = (BigDecimal) stack.pop(); BigDecimal subResult; if (operator == '+') { subResult = num2.add(num1); stack.push(subResult); } else if (operator == '-') { subResult = num2.subtract(num1); stack.push(subResult); } else if (operator == '*') { subResult = num2.multiply(num1); stack.push(subResult); } else { if ("0".equals(num1.toString())) { result = "不能除以零"; return; } else if ("0".equals(num2.toString())) { stack.push(new BigDecimal("0")); } else { subResult = num2.divide(num1, 20, BigDecimal.ROUND_HALF_UP); stack.push(subResult); } } } else { stack.push((BigDecimal) obj); } } result = stack.pop().toString(); if (result.matches("[-]?\\d*[.]\\d*")) { int i = result.length() - 1; while (result.charAt(i) == '0') { i--; } if (result.charAt(i) == '.') { i--; } result = result.substring(0, i + 1); } } }
分析
1、expression,result,textview等會多次使用,因此將其設置為成員變量。
2、顯示框根據行數自動放大或縮小。使用textView.setAutoSizeTextTypeUniformWithConfiguration(4, 70, 10, TypedValue.COMPLEX_UNIT_DIP);方法控制。第一個參數表示最小大小,第二個參數表示最大大小,第三個參數表示每次縮小步長,第四個參數表示之前參數的單位(如:dp,sp等)。
按鈕點擊詳解
3、除了按下等號鍵顯示計算結果,其余按鍵都不需要顯示,因此將結果顯示框設為空。
4、輸入數字時,如果前一個是數字“0”,按下其他數字應顯示該數字,即顯示“1”而不是“01”。
5、按下加減運算符時,如果之前有計算結果,應直接使用該結果運算。
6、表達式優化:以“-”號開頭的表達式,可以在前加上零方便計算;如果左括號少于右括號,此表達式無法計算;左括號少于右括號,可以在末尾補全右括號;表達式以“+”“-”號結尾,應補上0,以“*”“/”結尾,應補上1;對于a(b),(a)b應自動補上乘號
中綴表達式轉后綴表達式
1、遇到數字以及小數點直接保存,遇到符號按照優先級順序出棧入棧。
2、使用計數器分別記錄運算符和數字的個數,如果不匹配,直接顯示出錯
計算
1、在除法運算中,“0/a”應直接顯示0、“a/0”應不計算,直接顯示不能除以零
2、在最后結果上,“2.000000…”的類似有末尾0的結果應去除末尾0以及小數點
以上就是“Android如何實現計算器功能”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。