实验目的:
自主完成一个简单APP的设计工作,综合应用已经学到的Android UI设计技巧,重点注意合理使用布局。
实验要求:
- 完成一个计算器的设计,可以以手机自带的计算器为参考。设计过程中,注意考虑界面的美观性,不同机型的适应性,以及功能的完备性。
- 注意结合Activity的生命周期,考虑不同情况下计算器的界面状态。
- 如有余力,可以考虑实现一个高精度科学计算型的计算器。
项目文件结构:
1 package com.example.flyuz.calculator; 2 3 import android.support.v7.app.AppCompatActivity; 4 import android.os.Bundle; 5 import android.view.View; 6 import android.widget.Button; 7 import android.widget.EditText; 8 import android.content.res.Configuration; 9 import java.util.ArrayList; 10 import java.util.LinkedList; 11 import java.util.List; 12 13 public class MainActivity 14 extends AppCompatActivity implements View.OnClickListener { 15 // 16 Button btn_1, btn_2, btn_3, btn_4, btn_5, btn_6, btn_7, btn_8, btn_9, btn_0, btn_point; 17 // 18 Button btn_plus, btn_minus, btn_mul, btn_div; 19 // 20 Button btn_clear, btn_del, btn_l, btn_r, btn_res; 21 // 22 EditText input; 23 24 StringBuffer res = new StringBuffer(); 25 26 String errorMsg = "表达式错误"; 27 28 private void initView() { 29 btn_0 = (Button) findViewById(R.id.btn_0); 30 btn_1 = (Button) findViewById(R.id.btn_1); 31 btn_2 = (Button) findViewById(R.id.btn_2); 32 btn_3 = (Button) findViewById(R.id.btn_3); 33 btn_4 = (Button) findViewById(R.id.btn_4); 34 btn_5 = (Button) findViewById(R.id.btn_5); 35 btn_6 = (Button) findViewById(R.id.btn_6); 36 btn_7 = (Button) findViewById(R.id.btn_7); 37 btn_8 = (Button) findViewById(R.id.btn_8); 38 btn_9 = (Button) findViewById(R.id.btn_9); 39 btn_l = (Button) findViewById(R.id.btn_l); 40 btn_r = (Button) findViewById(R.id.btn_r); 41 42 btn_point = (Button) findViewById(R.id.btn_point); 43 btn_div = (Button) findViewById(R.id.btn_div); 44 btn_mul = (Button) findViewById(R.id.btn_mul); 45 btn_minus = (Button) findViewById(R.id.btn_minus); 46 btn_plus = (Button) findViewById(R.id.btn_plus); 47 btn_clear = (Button) findViewById(R.id.btn_clear); 48 btn_del = (Button) findViewById(R.id.btn_del); 49 btn_res = (Button) findViewById(R.id.btn_res); 50 51 input = (EditText) findViewById(R.id.input); 52 53 btn_0.setOnClickListener(this); 54 btn_1.setOnClickListener(this); 55 btn_2.setOnClickListener(this); 56 btn_3.setOnClickListener(this); 57 btn_4.setOnClickListener(this); 58 btn_5.setOnClickListener(this); 59 btn_6.setOnClickListener(this); 60 btn_7.setOnClickListener(this); 61 btn_8.setOnClickListener(this); 62 btn_9.setOnClickListener(this); 63 btn_point.setOnClickListener(this); 64 65 btn_l.setOnClickListener(this); 66 btn_r.setOnClickListener(this); 67 btn_del.setOnClickListener(this); 68 btn_clear.setOnClickListener(this); 69 btn_plus.setOnClickListener(this); 70 btn_minus.setOnClickListener(this); 71 btn_mul.setOnClickListener(this); 72 btn_div.setOnClickListener(this); 73 btn_res.setOnClickListener(this); 74 } 75 76 @Override 77 protected void onCreate(Bundle savedInstanceState) { 78 super.onCreate(savedInstanceState); 79 setContentView(R.layout.activity_main); 80 initView(); 81 } 82 @Override 83 public void onClick(View v) { 84 85 switch (v.getId()) { 86 case R.id.btn_0: 87 res.append("0"); 88 input.setText(res); 89 break; 90 case R.id.btn_1: 91 res.append("1"); 92 input.setText(res); 93 break; 94 case R.id.btn_2: 95 res.append("2"); 96 input.setText(res); 97 break; 98 case R.id.btn_3: 99 res.append("3");100 input.setText(res);101 break;102 case R.id.btn_4:103 res.append("4");104 input.setText(res);105 break;106 case R.id.btn_5:107 res.append("5");108 input.setText(res);109 break;110 case R.id.btn_6:111 res.append("6");112 input.setText(res);113 break;114 case R.id.btn_7:115 res.append("7");116 input.setText(res);117 break;118 case R.id.btn_8:119 res.append("8");120 input.setText(res);121 break;122 case R.id.btn_9:123 res.append("9");124 input.setText(res);125 break;126 case R.id.btn_l:127 res.append("(");128 input.setText(res);129 break;130 case R.id.btn_r:131 res.append(")");132 input.setText(res);133 break;134 case R.id.btn_point:135 res.append(".");136 input.setText(res);137 break;138 case R.id.btn_plus:139 res.append("+");140 input.setText(res);141 break;142 case R.id.btn_minus:143 res.append("-");144 input.setText(res);145 break;146 case R.id.btn_mul:147 res.append("*");148 input.setText(res);149 break;150 case R.id.btn_div:151 res.append("/");152 input.setText(res);153 break;154 case R.id.btn_del:155 if (res.length() != 0) {156 res.deleteCharAt(res.length() - 1);157 input.setText(res);158 }159 break;160 case R.id.btn_clear:161 res.setLength(0);162 input.setText(res);163 break;164 case R.id.btn_res:165 res.append("=");166 String in = new String(res);167 String out = prepareParam(in);168 res.setLength(0);169 res.append(out);170 input.setText(out);171 break;172 }173 }174 175 public String prepareParam(String str) {176 if (str == null || str.length() == 0 || str.length() > 20) {177 return errorMsg;178 }179 if (str.charAt(0) == '-') {180 str = "0" + str;181 }182 if (!tools.checkFormat(str)) {183 return errorMsg;184 }185 // 处理表达式,改为标准表达式186 str = tools.change2StandardFormat(str);187 // 拆分字符和数字188 String[] nums = str.split("[^.0-9]");189 ListnumLst = new ArrayList();190 for (int i = 0; i < nums.length; i++) {191 if (!"".equals(nums[i])) {192 numLst.add(Double.parseDouble(nums[i]));193 }194 }195 String symStr = str.replaceAll("[.0-9]", "");196 return doCalculate(symStr, numLst);197 }198 199 public String doCalculate(String symStr, List numLst) {200 String errorMsg = "表达式错误";201 LinkedList symStack = new LinkedList<>(); // 符号栈202 LinkedList numStack = new LinkedList<>(); // 数字栈203 int i = 0; // numLst的标志位204 int j = 0; // symStr的标志位205 char sym; // 符号206 double num1, num2; // 符号前后两个数207 while (symStack.isEmpty() || !(symStack.getLast() == '=' && symStr.charAt(j) == '=')) {208 if (symStack.isEmpty()) {209 symStack.add('=');210 numStack.add(numLst.get(i++));211 }212 if (tools.symLvMap.get(symStr.charAt(j)) > tools.symLvMap.get(symStack.getLast())) { // 比较符号优先级,若当前符号优先级大于前一个则压栈213 if (symStr.charAt(j) == '(') {214 symStack.add(symStr.charAt(j++));215 continue;216 }217 numStack.add(numLst.get(i++));218 symStack.add(symStr.charAt(j++));219 } else { // 当前符号优先级小于等于前一个 符号的优先级220 if (symStr.charAt(j) == ')' && symStack.getLast() == '(') { // 若()之间没有符号,则“(”出栈221 j++;222 symStack.removeLast();223 continue;224 }225 if (symStack.getLast() == '(') { // “(”直接压栈226 numStack.add(numLst.get(i++));227 symStack.add(symStr.charAt(j++));228 continue;229 }230 num2 = numStack.removeLast();231 num1 = numStack.removeLast();232 sym = symStack.removeLast();233 switch (sym) {234 case '+':235 numStack.add(tools.plus(num1, num2));236 break;237 case '-':238 numStack.add(tools.reduce(num1, num2));239 break;240 case '*':241 numStack.add(tools.multiply(num1, num2));242 break;243 case '/':244 if (num2 == 0) { // 除数为0245 return errorMsg;246 }247 numStack.add(tools.divide(num1, num2));248 break;249 }250 }251 }252 return String.valueOf(numStack.removeLast());253 }254 }
1 package com.example.flyuz.calculator; 2 3 import java.util.HashMap; 4 import java.util.LinkedList; 5 import java.util.Map; 6 import java.math.BigDecimal; 7 8 public class tools { 9 public static final int RESULT_DECIMAL_MAX_LENGTH = 10 8; // 结果小数点最大长度限制 11 public static final MapsymLvMap = 12 new HashMap (); // 符号优先级map 13 14 static { 15 symLvMap.put('=', 0); 16 symLvMap.put('-', 1); 17 symLvMap.put('+', 1); 18 symLvMap.put('*', 2); 19 symLvMap.put('/', 2); 20 symLvMap.put('(', 3); 21 symLvMap.put(')', 1); 22 } 23 24 public static boolean checkFormat(String str) { 25 // 校验是否以“=”结尾 26 if ('=' != str.charAt(str.length() - 1)) { 27 return false; 28 } 29 // 校验开头是否为数字或者“(” 30 if (!(isCharNum(str.charAt(0)) || str.charAt(0) == '(')) { 31 return false; 32 } 33 char c; 34 // 校验 35 for (int i = 1; i < str.length() - 1; i++) { 36 c = str.charAt(i); 37 if (!isCorrectChar(c)) { // 字符不合法 38 return false; 39 } 40 if (!(isCharNum(c))) { 41 if (c == '-' || c == '+' || c == '*' || c == '/') { 42 if (c == '-' && str.charAt(i - 1) == '(') { // 1*(-2+3)的情况 43 continue; 44 } 45 if (!(isCharNum(str.charAt(i - 1)) || 46 str.charAt(i - 1) == ')')) { // 若符号前一个不是数字或者“)”时 47 return false; 48 } 49 } 50 if (c == '.') { 51 if (!isCharNum(str.charAt(i - 1)) || 52 !isCharNum(str.charAt(i + 1))) { // 校验“.”的前后是否位数字 53 return false; 54 } 55 } 56 } 57 } 58 return isBracketCouple(str); // 校验括号是否配对 59 } 60 61 public static String change2StandardFormat(String str) { 62 StringBuilder sb = new StringBuilder(); 63 char c; 64 for (int i = 0; i < str.length(); i++) { 65 c = str.charAt(i); 66 if (i != 0 && c == '(' && 67 (isCharNum(str.charAt(i - 1)) || str.charAt(i - 1) == ')')) { 68 sb.append("*("); 69 continue; 70 } 71 if (c == '-' && str.charAt(i - 1) == '(') { 72 sb.append("0-"); 73 continue; 74 } 75 sb.append(c); 76 } 77 return sb.toString(); 78 } 79 80 private static boolean isBracketCouple(String str) { 81 LinkedList stack = new LinkedList<>(); 82 for (char c : str.toCharArray()) { 83 if (c == '(') { 84 stack.add(c); 85 } else if (c == ')') { 86 if (stack.isEmpty()) { 87 return false; 88 } 89 stack.removeLast(); 90 } 91 } 92 if (stack.isEmpty()) { 93 return true; 94 } else { 95 return false; 96 } 97 } 98 99 public static String formatResult(String str) {100 String[] ss = str.split("\\.");101 if (Integer.parseInt(ss[1]) == 0) {102 return ss[0]; // 整数103 }104 String s1 = new StringBuilder(ss[1]).reverse().toString();105 int start = 0;106 for (int i = 0; i < s1.length(); i++) {107 if (s1.charAt(i) != '0') {108 start = i;109 break;110 }111 }112 return ss[0] + "." +113 new StringBuilder(s1.substring(start, s1.length())).reverse();114 }115 116 private static boolean isCorrectChar(Character c) {117 if (('0' <= c && c <= '9') || c == '-' || c == '+' || c == '*' ||118 c == '/' || c == '(' || c == ')' || c == '.') {119 return true;120 }121 return false;122 }123 124 private static boolean isCharNum(Character c) {125 if (c >= '0' && c <= '9') {126 return true;127 }128 return false;129 }130 131 public static double plus(double num1, double num2) {132 BigDecimal b1 = new BigDecimal(num1);133 BigDecimal b2 = new BigDecimal(num2);134 return b1.add(b2).setScale(8,BigDecimal.ROUND_HALF_DOWN).doubleValue();135 }136 137 public static double reduce(double num1, double num2) {138 BigDecimal b1 = new BigDecimal(num1);139 BigDecimal b2 = new BigDecimal(num2);140 return b1.subtract(b2).setScale(8,BigDecimal.ROUND_HALF_DOWN).doubleValue();141 142 }143 144 public static double multiply(double num1, double num2) {145 BigDecimal b1 = new BigDecimal(num1);146 BigDecimal b2 = new BigDecimal(num2);147 return b1.multiply(b2).setScale(8,BigDecimal.ROUND_HALF_DOWN).doubleValue();148 }149 150 public static double divide(double num1, double num2) {151 BigDecimal b1 = new BigDecimal(num1);152 BigDecimal b2 = new BigDecimal(num2);153 return b1.divide(b2, 8, BigDecimal.ROUND_HALF_UP).doubleValue();154 }155 }
1 27 8 160 16116 17 22 23 30 31 38 39 46 47 54 55 62 63 64 6570 71 78 79 86 87 94 95 102 103 112 113110 111 118 119 126 127 134 135 142 143 150 151 158 159 166 167 174 175 182 183 190 191 198 199 206 207 208 209
1 28 9 145 14617 18 24 25 30 31 36 37 42 43 48 49 5056 57 62 63 68 69 74 75 80 81 8288 89 94 95 100 101 113 114106 107 112 120 121 126 127 132 133 138 139 144 152 153 158 159 164 165 170 171 176 177 178 179
1 24 5 12 21 2214 2015 1916 17 18