本次APP的源码已上传到我的GitHub:https://github.com/zdm-code/Android-learning/tree/master/android_learning/app
经过长达两天的Android的学习,觉得已经可以做一些简单的小APP练练手。本次就做了一个简易计算器,下面简单记录一下开发过程。
本次开发运用了前几次关于Android博文里的一些内容。主要使用了几个基本的控件,通过drawable设计控件样式,通过线性布局将所有控件串联起来。
计算器是人们生活中最常用的工具之一,无论在电脑上还是手机上,都少不了计算器的身影。原本以为计算器的开发还是蛮简单的,结果在前端写好之后,一进入activity的java代码编写就发现了很多细节问题。如:用户非法数据的输入判断(例如00012,1.23.45,1+*3等等)以及用户体验等,通过简单的点击打印的方式会很容易导致数据不合法,因此后台需要判断并控制用户的输入数据。
先来简单对比一下手机自带的计算器和自己开发的计算器
如图所见,样子还是比较相似的(其实是照着手机上自带的样子开发的)。我的计算器有三部分组成:标题,显示区(TextView),按键区(Button),它能实现基本的加减乘除运算功能(包括连续表达式的求值),体验感已和手机自带计算器基本一致。
这里不再给出布局代码,仅附上activity的java代码
1 package com.example.animator.android_learning;
2
3 import android.content.Context;
4 import android.support.v7.app.ActionBarActivity;
5 import android.os.Bundle;
6 import android.util.DisplayMetrics;
7 import android.view.View;
8 import android.view.WindowManager;
9 import android.widget.Button;
10 import android.widget.TextView;
11 import android.widget.Toast;
12
13 import com.example.animator.utils.Calculator;
14 import com.example.animator.utils.IsSecondNumZero;
15
16 public class MainActivity extends ActionBarActivity implements View.OnClickListener {
17
18 TextView textView;
19 Button btn_1;
20 Button btn_2;
21 Button btn_3;
22 Button btn_4;
23 Button btn_5;
24 Button btn_6;
25 Button btn_7;
26 Button btn_8;
27 Button btn_9;
28 Button btn_10;
29 Button btn_11;
30 Button btn_12;
31 Button btn_13;
32 Button btn_14;
33 Button btn_15;
34 Button btn_16;
35 Button btn_17;
36 Button btn_18;
37 Button btn_19;
38
39 @Override
40 protected void onCreate(Bundle savedInstanceState) {
41 super.onCreate(savedInstanceState);
42 setContentView(R.layout.activity_main);
43 textView= (TextView) findViewById(R.id.tv_show);
44 btn_1= (Button) findViewById(R.id.btn_1);
45 btn_2= (Button) findViewById(R.id.btn_2);
46 btn_3= (Button) findViewById(R.id.btn_3);
47 btn_4= (Button) findViewById(R.id.btn_4);
48 btn_5= (Button) findViewById(R.id.btn_5);
49 btn_6= (Button) findViewById(R.id.btn_6);
50 btn_7= (Button) findViewById(R.id.btn_7);
51 btn_8= (Button) findViewById(R.id.btn_8);
52 btn_9= (Button) findViewById(R.id.btn_9);
53 btn_10= (Button) findViewById(R.id.btn_10);
54 btn_11= (Button) findViewById(R.id.btn_11);
55 btn_12= (Button) findViewById(R.id.btn_12);
56 btn_13= (Button) findViewById(R.id.btn_13);
57 btn_14= (Button) findViewById(R.id.btn_14);
58 btn_15= (Button) findViewById(R.id.btn_15);
59 btn_16= (Button) findViewById(R.id.btn_16);
60 btn_17= (Button) findViewById(R.id.btn_17);
61 btn_18= (Button) findViewById(R.id.btn_18);
62 btn_19= (Button) findViewById(R.id.btn_19);
63
64 btn_1.setOnClickListener(this);
65 btn_2.setOnClickListener(this);
66 btn_3.setOnClickListener(this);
67 btn_4.setOnClickListener(this);
68 btn_5.setOnClickListener(this);
69 btn_6.setOnClickListener(this);
70 btn_7.setOnClickListener(this);
71 btn_8.setOnClickListener(this);
72 btn_9.setOnClickListener(this);
73 btn_10.setOnClickListener(this);
74 btn_11.setOnClickListener(this);
75 btn_12.setOnClickListener(this);
76 btn_13.setOnClickListener(this);
77 btn_14.setOnClickListener(this);
78 btn_15.setOnClickListener(this);
79 btn_16.setOnClickListener(this);
80 btn_17.setOnClickListener(this);
81 btn_18.setOnClickListener(this);
82 btn_19.setOnClickListener(this);
83
84
85
86 }
87
88
89 //根据手机的分辨率从dp单位转换成px单位
90 public static int dip2px(Context context,float dpValue){
91 //获取当前手机的像素密度
92 final float scale=context.getResources().getDisplayMetrics().density;
93 return (int)(dpValue*scale+0.5f); //四舍五入取整
94 }
95
96 //根据手机的分辨率从px单位转换成dp单位
97 public static int px2dip(Context context,float pxValue){
98 //获取当前手机的像素密度
99 final float scale=context.getResources().getDisplayMetrics().density;
100 return (int)(pxValue/scale+0.5f); //四舍五入取整
101 }
102
103 public static int getScreenWidth(Context context){
104 //从系统服务中获取窗口管理器
105 WindowManager windowManager=(WindowManager)context.getSystemService(context.WINDOW_SERVICE);
106 DisplayMetrics displayMetrics=new DisplayMetrics();
107 //从默认显示器中获取显示参数保存到displayMetrics对象中
108 windowManager.getDefaultDisplay().getMetrics(displayMetrics);
109 return displayMetrics.widthPixels; //返回屏幕的宽度数值
110 }
111
112 public static int getScreenHeight(Context context){
113 //从系统服务中获取窗口管理器
114 WindowManager windowManager=(WindowManager)context.getSystemService(context.WINDOW_SERVICE);
115 DisplayMetrics displayMetrics=new DisplayMetrics();
116 //从默认显示器中获取显示参数保存到displayMetrics对象中
117 windowManager.getDefaultDisplay().getMetrics(displayMetrics);
118 return displayMetrics.heightPixels; //返回屏幕的高度数值
119 }
120
121 public static float getScreenDensity(Context context){
122 //从系统服务中获取窗口管理器
123 WindowManager windowManager=(WindowManager)context.getSystemService(context.WINDOW_SERVICE);
124 DisplayMetrics displayMetrics=new DisplayMetrics();
125 //从默认显示器中获取显示参数保存到displayMetrics对象中
126 windowManager.getDefaultDisplay().getMetrics(displayMetrics);
127 return displayMetrics.density; //返回屏幕的高度数值
128 }
129
130 @Override
131 public void onClick(View view) {
132 String text=textView.getText().toString();
133 String[] number=text.split("[+|-|*|/|=]");
134 String lastnumber="";
135 if(number.length>0)
136 lastnumber=number[number.length-1];
137 switch (view.getId()){
138 case R.id.btn_1:
139 case R.id.btn_16://删除数字键,计算完毕后点击全部清除,表达式书写中则去除最后一个字符
140 if(text.contains("=")){
141 textView.setText("");
142 }else {
143 if (text.length() > 0)
144 textView.setText(text.substring(0, text.length() - 1));
145 }
146 break;
147 case R.id.btn_2:
148 //除号键,判定是否计算完成,若完成则取结果继续运算
149 if(text.length()>0) {
150 if(text.contains("=")){
151 textView.setText(lastnumber+"/");
152 }
153 //判断前面字符是否为符号,若是,则将其改为当前输入符号(注意两符号不能同时出现)
154 else {
155 if (text.substring(text.length() - 1).equals("+") == false && text.substring(text.length() - 1).equals("-") == false && text.substring(text.length() - 1).equals("*") == false &&
156 text.substring(text.length() - 1).equals("/") == false && text.substring(text.length() - 1).equals(".") == false)
157 textView.setText(text + "/");
158 else if (text.substring(text.length() - 1).equals("+") == true || text.substring(text.length() - 1).equals("-") == true || text.substring(text.length() - 1).equals("*") == true ||
159 text.substring(text.length() - 1).equals("/") == true)
160 textView.setText(text.substring(0, text.length() - 1) + "/");
161 }
162 }
163 break;
164 case R.id.btn_3:
165 //乘号键,用法大致同除号
166 if(text.length()>0) {
167 if(text.contains("=")){
168 textView.setText(lastnumber+"*");
169 }
170 else {
171 if (text.substring(text.length() - 1).equals("+") == false && text.substring(text.length() - 1).equals("-") == false && text.substring(text.length() - 1).equals("*") == false &&
172 text.substring(text.length() - 1).equals("/") == false && text.substring(text.length() - 1).equals(".") == false)
173 textView.setText(text + "*");
174 else if (text.substring(text.length() - 1).equals("+") == true || text.substring(text.length() - 1).equals("-") == true || text.substring(text.length() - 1).equals("*") == true ||
175 text.substring(text.length() - 1).equals("/") == true)
176 textView.setText(text.substring(0, text.length() - 1) + "*");
177 }
178 }
179 break;
180 case R.id.btn_4:
181 //全部清除键
182 textView.setText("");
183 break;
184 case R.id.btn_5:
185 //数字7,判断组合数字首位是否为0,若是,则将其置为7,下面数字用法类似
186 if(text.contains("="))
187 {
188 textView.setText("7");
189 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
190 {
191 textView.setText(text.substring(0, text.length() - 1) + "7");
192 }else
193 textView.setText(text+"7");
194 break;
195 case R.id.btn_6:
196 if(text.contains("="))
197 {
198 textView.setText("8");
199 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
200 {
201 textView.setText(text.substring(0, text.length() - 1) + "8");
202 }else
203 textView.setText(text+"8");
204 break;
205 case R.id.btn_7:
206 if(text.contains("="))
207 {
208 textView.setText("9");
209 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
210 {
211 textView.setText(text.substring(0, text.length() - 1) + "9");
212 }else
213 textView.setText(text+"9");
214 break;
215 case R.id.btn_8:
216 if(text.length()>0) {
217 if(text.contains("=")){
218 textView.setText(lastnumber+"+");
219 }
220 else {
221 if (text.substring(text.length() - 1).equals("+") == false && text.substring(text.length() - 1).equals("-") == false && text.substring(text.length() - 1).equals("*") == false &&
222 text.substring(text.length() - 1).equals("/") == false && text.substring(text.length() - 1).equals(".") == false)
223 textView.setText(text + "+");
224 else if (text.substring(text.length() - 1).equals("+") == true || text.substring(text.length() - 1).equals("-") == true || text.substring(text.length() - 1).equals("*") == true ||
225 text.substring(text.length() - 1).equals("/") == true)
226 textView.setText(text.substring(0, text.length() - 1) + "+");
227 }
228 }
229 break;
230 case R.id.btn_9:
231 if(text.contains("="))
232 {
233 textView.setText("4");
234 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
235 {
236 textView.setText(text.substring(0, text.length() - 1) + "4");
237 }else
238 textView.setText(text+"4");
239 break;
240 case R.id.btn_10:
241 if(text.contains("="))
242 {
243 textView.setText("5");
244 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
245 {
246 textView.setText(text.substring(0, text.length() - 1) + "5");
247 }else
248 textView.setText(text+"5");
249 break;
250 case R.id.btn_11:
251 if(text.contains("="))
252 {
253 textView.setText("6");
254 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
255 {
256 textView.setText(text.substring(0, text.length() - 1) + "6");
257 }else
258 textView.setText(text+"6");
259 break;
260 case R.id.btn_12:
261 if(text.length()>0) {
262 if(text.contains("=")){
263 textView.setText(lastnumber+"-");
264 }
265 else {
266 if (text.substring(text.length() - 1).equals("+") == false && text.substring(text.length() - 1).equals("-") == false && text.substring(text.length() - 1).equals("*") == false &&
267 text.substring(text.length() - 1).equals("/") == false && text.substring(text.length() - 1).equals(".") == false)
268 textView.setText(text + "-");
269 else if (text.substring(text.length() - 1).equals("+") == true || text.substring(text.length() - 1).equals("-") == true || text.substring(text.length() - 1).equals("*") == true ||
270 text.substring(text.length() - 1).equals("/") == true)
271 textView.setText(text.substring(0, text.length() - 1) + "-");
272 }
273 }
274 break;
275 case R.id.btn_13:
276 if(text.contains("="))
277 {
278 textView.setText("1");
279 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
280 {
281 textView.setText(text.substring(0, text.length() - 1) + "1");
282 }else
283 textView.setText(text+"1");
284 break;
285 case R.id.btn_14:
286 if(text.contains("="))
287 {
288 textView.setText("2");
289 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
290 {
291 textView.setText(text.substring(0, text.length() - 1) + "2");
292 }else
293 textView.setText(text+"2");
294 break;
295 case R.id.btn_15:
296 if(text.contains("="))
297 {
298 textView.setText("3");
299 }else if((text.length()>2&&text.charAt(text.length()-1)=='0'&&isOperation(text.charAt(text.length()-2)))||(text.length()==1&&text.charAt(0)=='0'))
300 {
301 textView.setText(text.substring(0, text.length() - 1) + "3");
302 }else
303 textView.setText(text+"3");
304 break;
305 case R.id.btn_17:
306 if(text.contains("="))
307 {
308 textView.setText("0");
309 }else {
310 //判断当前数字是否仅为“0”,即不包含小数点,数字头不能出现多个0
311 if (lastnumber.equals("0") == false)
312 textView.setText(text + "0");
313 }
314 break;
315 case R.id.btn_18:
316 //小数点,判断是否计算完成,若是,则打印0.
317 if(text.contains("="))
318 {
319 textView.setText("0.");
320 }else if(lastnumber.contains(".")==false){//保证同一数字里只有一个小数点
321 if (text.length() > 0) {
322 if (text.substring(text.length() - 1).equals("+") == false && text.substring(text.length() - 1).equals("-") == false && text.substring(text.length() - 1).equals("*") == false &&
323 text.substring(text.length() - 1).equals("/") == false && text.substring(text.length() - 1).equals(".") == false)
324 textView.setText(text + ".");
325 else if (text.substring(text.length() - 1).equals("+") == true || text.substring(text.length() - 1).equals("-") == true || text.substring(text.length() - 1).equals("*") == true ||
326 text.substring(text.length() - 1).equals("/") == true)
327 textView.setText(text + "0.");
328 } else {
329 textView.setText("0.");
330 }
331 }
332 break;
333 case R.id.btn_19:
334 if(text.contains("=")==false) {
335 if (IsSecondNumZero.isAvailable(text + "=")) {//判断除法是除数为0的情况
336 Toast.makeText(MainActivity.this, "除数不能为0", Toast.LENGTH_LONG).show();
337 } else {//通过栈进行结果运算
338 Calculator calculator = new Calculator();
339 String result = calculator.convertDoubleToString(calculator.calculate(text));
340 textView.setText(text + "=" + result);
341 }
342 }
343 break;
344 }
345 }
346
347 public boolean isOperation(char c){
348 return c=='+'||c=='-'||c=='*'||c=='/';
349 }
350 }
其中有一些冗余的代码,读者可自行缩减。
下面再附上除法判断除数为0的代码(由于是最后求值,表达式中可能有多个除号,所以需要遍历所有除号)
1 package com.example.animator.utils;
2
3 import android.util.Log;
4
5 import java.math.BigDecimal;
6 import java.util.ArrayList;
7
8 /**
9 * Created by animator on 2020/1/14.
10 */
11 public class IsSecondNumZero {
12 public static boolean isAvailable(String str){
13 ArrayList<Integer> divlist=new ArrayList<>();//储存除号索引
14 ArrayList<Integer> alllist=new ArrayList<>();//储存所有运算符索引
15
16 for(int i=0;i<str.length();i++)
17 {
18 if(str.charAt(i)=='/')
19 {
20 divlist.add(i);
21 alllist.add(i);
22 }
23 else if(str.charAt(i)=='+'||str.charAt(i)=='-'||str.charAt(i)=='*'||str.charAt(i)=='=')
24 {
25 alllist.add(i);
26 }
27 }
28 Log.v("divsize",divlist.size()+"");
29 Log.v("allsize",alllist.size()+"");
30 for(int i=0;i<divlist.size();i++){
31 String string=str.substring(divlist.get(i)+1,alllist.get(alllist.indexOf(divlist.get(i)) + 1));
32 BigDecimal num = new BigDecimal(string);
33 if(num.compareTo(new BigDecimal("0"))==0)
34 return true;
35 }
36 return false;
37
38 }
39 }