首页 > 代码库 > Android 开发笔记___初级控件之实战__计算器

Android 开发笔记___初级控件之实战__计算器

技术分享

 

功能简单,实现并不难,对于初学者可以总和了解初级控件的基本使用。

  用到的知识点如下:

  • 线性布局 LinearLayout:整体界面是从上往下的,因此需要垂直方向的linearlayout;下面每行四个按钮,需要水平的linearlayout。
  • 滚动视图 ScrollView    :虽然界面不宽也不高,以防万一,有可能会遇到屏幕特别小的手机,因此用一个垂直方向的scrollview。
  • 文本视图 TextView      :上面标题就是一个textview,结果显示也是textview,但是更高级。能够从下往上滚动,前面的聊天室效果里用到过。
  • 按钮  Button                :下面的数字、运算符都是按钮。
  • 图像视图 ImageView  :未用到。
  • 图像按钮 ImageButton :由于开根号运算符(√)虽然可以打出来,但是有点不一样,因此需要用到一个图像,就用到了图像按钮。
  • 状态列表图形              :都有按下和弹起两种状态,因此订制了按钮的自定义样式。
  • 形状图形                :运算结果用到的textview是一个圆角的矩形,所以定义了shape文件,把它作为文本视图的背景。
  • 九宫格图片                 :最下面的“0”按钮是有点大,因此需要两倍那么大的图片,如果使用普通的图片则会拉宽,效果很不好。因此就用到了。

style

 1 <resources>
 2 
 3     <!-- Base application theme. -->
 4     <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
 5         <!-- Customize your theme here. -->
 6         <item name="colorPrimary">@color/colorPrimary</item>
 7         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
 8         <item name="colorAccent">@color/colorAccent</item>
 9     </style>
10     <style name="btn_cal">
11         <item name="android:layout_width">0dp</item>
12         <item name="android:layout_height">match_parent</item>
13         <item name="android:layout_weight">1</item>
14         <item name="android:gravity">center</item>
15         <item name="android:textColor">@color/black</item>
16         <item name="android:textSize">30sp</item>
17         <item name="android:background">@drawable/btn_nine_selector</item>
18     </style>
19 
20 </resources>

xml

  1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2     android:layout_width="match_parent"
  3     android:layout_height="match_parent"
  4     android:padding="5dp"
  5     android:gravity="top|center"
  6     android:orientation="vertical">
  7 
  8     <ScrollView
  9         android:layout_width="match_parent"
 10         android:layout_height="wrap_content">
 11 
 12         <LinearLayout
 13             android:layout_width="match_parent"
 14             android:layout_height="wrap_content"
 15             android:orientation="vertical">
 16 
 17             <TextView
 18                 android:layout_width="match_parent"
 19                 android:layout_height="wrap_content"
 20                 android:gravity="center"
 21                 android:text="简单计算器"
 22                 android:textColor="#000000"
 23                 android:textSize="22sp" />
 24 
 25             <LinearLayout
 26                 android:layout_width="match_parent"
 27                 android:layout_height="wrap_content"
 28                 android:background="@drawable/shape_white_with_stroke"
 29                 android:orientation="vertical">
 30 
 31                 <TextView
 32                     android:id="@+id/tv_result"
 33                     android:layout_width="match_parent"
 34                     android:layout_height="wrap_content"
 35                     android:gravity="right|bottom"
 36                     android:lines="3"
 37                     android:maxLines="3"
 38                     android:scrollbars="vertical"
 39                     android:textColor="#000000"
 40                     android:textSize="25sp" />
 41             </LinearLayout>
 42 
 43             <LinearLayout
 44                 android:layout_width="match_parent"
 45                 android:layout_height="wrap_content"
 46                 android:orientation="vertical">
 47 
 48                 <LinearLayout
 49                     android:layout_width="match_parent"
 50                     android:layout_height="75dp"
 51                     android:orientation="horizontal">
 52 
 53                     <Button
 54                         android:id="@+id/btn_cancel"
 55                         style="@style/btn_cal"
 56                         android:text="CE" />
 57 
 58                     <Button
 59                         android:id="@+id/btn_divide"
 60                         style="@style/btn_cal"
 61                         android:text="÷" />
 62 
 63                     <Button
 64                         android:id="@+id/btn_multiply"
 65                         style="@style/btn_cal"
 66                         android:text="×" />
 67 
 68                     <Button
 69                         android:id="@+id/btn_clear"
 70                         style="@style/btn_cal"
 71                         android:text="C" />
 72                 </LinearLayout>
 73 
 74                 <LinearLayout
 75                     android:layout_width="match_parent"
 76                     android:layout_height="75dp"
 77                     android:orientation="horizontal">
 78 
 79                     <Button
 80                         android:id="@+id/btn_seven"
 81                         style="@style/btn_cal"
 82                         android:text="7" />
 83 
 84                     <Button
 85                         android:id="@+id/btn_eight"
 86                         style="@style/btn_cal"
 87                         android:text="8" />
 88 
 89                     <Button
 90                         android:id="@+id/btn_nine"
 91                         style="@style/btn_cal"
 92                         android:text="9" />
 93 
 94                     <Button
 95                         android:id="@+id/btn_plus"
 96                         style="@style/btn_cal"
 97                         android:text="+" />
 98                 </LinearLayout>
 99 
100                 <LinearLayout
101                     android:layout_width="match_parent"
102                     android:layout_height="75dp"
103                     android:orientation="horizontal">
104 
105                     <Button
106                         android:id="@+id/btn_four"
107                         style="@style/btn_cal"
108                         android:text="4" />
109 
110                     <Button
111                         android:id="@+id/btn_five"
112                         style="@style/btn_cal"
113                         android:text="5" />
114 
115                     <Button
116                         android:id="@+id/btn_six"
117                         style="@style/btn_cal"
118                         android:text="6" />
119 
120                     <Button
121                         android:id="@+id/btn_minus"
122                         style="@style/btn_cal"
123                         android:text="-" />
124                 </LinearLayout>
125 
126                 <LinearLayout
127                     android:layout_width="match_parent"
128                     android:layout_height="75dp"
129                     android:orientation="horizontal">
130 
131                     <Button
132                         android:id="@+id/btn_one"
133                         style="@style/btn_cal"
134                         android:text="1" />
135 
136                     <Button
137                         android:id="@+id/btn_two"
138                         style="@style/btn_cal"
139                         android:text="2" />
140 
141                     <Button
142                         android:id="@+id/btn_three"
143                         style="@style/btn_cal"
144                         android:text="3" />
145 
146                     <ImageButton
147                         android:id="@+id/ib_sqrt"
148                         android:layout_width="0dp"
149                         android:layout_height="match_parent"
150                         android:layout_weight="1"
151                         android:scaleType="centerInside"
152                         android:src="@drawable/sqrt"
153                         android:background="@drawable/btn_nine_selector"/>
154                 </LinearLayout>
155 
156                 <LinearLayout
157                     android:layout_width="match_parent"
158                     android:layout_height="75dp"
159                     android:orientation="horizontal">
160 
161                     <Button
162                         android:id="@+id/btn_zero"
163                         style="@style/btn_cal"
164                         android:layout_weight="2"
165                         android:text="0" />
166 
167                     <Button
168                         android:id="@+id/btn_dot"
169                         style="@style/btn_cal"
170                         android:text="." />
171 
172                     <Button
173                         android:id="@+id/btn_equal"
174                         style="@style/btn_cal"
175                         android:text="=" />
176                 </LinearLayout>
177             </LinearLayout>
178         </LinearLayout>
179     </ScrollView>
180 
181 </LinearLayout>

 

nineselec0tor

1 <?xml version="1.0" encoding="utf-8"?>
2 <selector xmlns:android="http://schemas.android.com/apk/res/android">
3     <item android:state_pressed="true" android:drawable="@drawable/button_pressed" />
4     <item android:drawable="@drawable/button_normal" />
5 </selector>

putong

1 <?xml version="1.0" encoding="utf-8"?>
2 <selector xmlns:android="http://schemas.android.com/apk/res/android">
3     <item android:state_pressed="true" android:drawable="@drawable/button_pressed_orig" />
4     <item android:drawable="@drawable/button_normal_orig" />
5 </selector>0

shape_oval

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <shape xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:shape="oval" >
 4 
 5     <solid android:color="#ff66aa" />
 6 
 7     <stroke
 8         android:width="1dp"
 9         android:color="#ffaaaaaa" />
10 
11 </shape>

rect

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <shape xmlns:android="http://schemas.android.com/apk/res/android" >
 3 
 4     <solid android:color="#ffdd66" />
 5 
 6     <stroke
 7         android:width="1dp"
 8         android:color="#ffaaaaaa" />
 9 
10     <corners
11         android:bottomLeftRadius="10dp"
12         android:bottomRightRadius="10dp"
13         android:topLeftRadius="10dp"
14         android:topRightRadius="10dp" />
15 
16 </shape>

white_stroke

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <shape xmlns:android="http://schemas.android.com/apk/res/android" >
 3 
 4     <solid android:color="#ffffff" />
 5 
 6     <stroke
 7         android:width="1dp"
 8         android:color="#bbbbbb" />
 9 
10     <corners
11         android:bottomLeftRadius="10dp"
12         android:bottomRightRadius="10dp"
13         android:topLeftRadius="10dp"
14         android:topRightRadius="10dp" />
15 
16 </shape>

main

  1 package com.example.alimjan.hello_world;
  2 
  3 import android.app.Activity;
  4 import android.content.Context;
  5 import android.content.Intent;
  6 import android.os.Bundle;
  7 import android.support.annotation.Nullable;
  8 
  9 /**
 10  * Created by alimjan on 7/1/2017.
 11  */
 12 
 13         import android.support.v7.app.AppCompatActivity;
 14         import android.text.method.ScrollingMovementMethod;
 15         import android.util.Log;
 16         import android.view.View;
 17         import android.widget.TextView;
 18         import android.widget.Toast;
 19 
 20 import com.example.alimjan.hello_world.Arith;
 21 
 22 
 23 public class class__2_5 extends AppCompatActivity implements View.OnClickListener {
 24 
 25     private final static String TAG = "CalculatorActivity";
 26     private TextView tv_result;
 27 
 28     @Override
 29     protected void onCreate(Bundle savedInstanceState) {
 30         super.onCreate(savedInstanceState);
 31         setContentView(R.layout.code_2_5);
 32         tv_result = (TextView) findViewById(R.id.tv_result);
 33         tv_result.setMovementMethod(new ScrollingMovementMethod());
 34 
 35         findViewById(R.id.btn_cancel).setOnClickListener(this);
 36         findViewById(R.id.btn_divide).setOnClickListener(this);
 37         findViewById(R.id.btn_multiply).setOnClickListener(this);
 38         findViewById(R.id.btn_clear).setOnClickListener(this);
 39         findViewById(R.id.btn_seven).setOnClickListener(this);
 40         findViewById(R.id.btn_eight).setOnClickListener(this);
 41         findViewById(R.id.btn_nine).setOnClickListener(this);
 42         findViewById(R.id.btn_plus).setOnClickListener(this);
 43         findViewById(R.id.btn_four).setOnClickListener(this);
 44         findViewById(R.id.btn_five).setOnClickListener(this);
 45         findViewById(R.id.btn_six).setOnClickListener(this);
 46         findViewById(R.id.btn_minus).setOnClickListener(this);
 47         findViewById(R.id.btn_one).setOnClickListener(this);
 48         findViewById(R.id.btn_two).setOnClickListener(this);
 49         findViewById(R.id.btn_three).setOnClickListener(this);
 50         findViewById(R.id.btn_zero).setOnClickListener(this);
 51         findViewById(R.id.btn_dot).setOnClickListener(this);
 52         findViewById(R.id.btn_equal).setOnClickListener(this);
 53         findViewById(R.id.ib_sqrt).setOnClickListener(this);
 54     }
 55 
 56     @Override
 57     public void onClick(View v) {
 58         int resid = v.getId();
 59         String inputText;
 60         if (resid == R.id.ib_sqrt) {
 61             inputText = "√";
 62         } else {
 63             inputText = ((TextView) v).getText().toString();
 64         }
 65         Log.d(TAG, "resid="+resid+",inputText="+inputText);
 66         if (resid == R.id.btn_clear) {
 67             clear("");
 68         } else if (resid == R.id.btn_cancel) {
 69             if (operator.equals("") == true) {
 70                 if (firstNum.length() == 1) {
 71                     firstNum = "0";
 72                 } else if (firstNum.length() > 0) {
 73                     firstNum = firstNum.substring(0, firstNum.length() - 1);
 74                 } else {
 75                     Toast.makeText(this, "没有可取消的数字了", Toast.LENGTH_SHORT).show();
 76                     return;
 77                 }
 78                 showText = firstNum;
 79                 tv_result.setText(showText);
 80             } else {
 81                 if (nextNum.length() == 1) {
 82                     nextNum = "";
 83                 } else if (nextNum.length() > 0) {
 84                     nextNum = nextNum.substring(0, nextNum.length() - 1);
 85                 } else {
 86                     Toast.makeText(this, "没有可取消的数字了", Toast.LENGTH_SHORT).show();
 87                     return;
 88                 }
 89                 showText = showText.substring(0, showText.length() - 1);
 90                 tv_result.setText(showText);
 91             }
 92         } else if (resid == R.id.btn_equal) {
 93             if (operator.length() == 0 || operator.equals("=") == true) {
 94                 Toast.makeText(this, "请输入运算符", Toast.LENGTH_SHORT).show();
 95                 return;
 96             } else if (nextNum.length() <= 0) {
 97                 Toast.makeText(this, "请输入数字", Toast.LENGTH_SHORT).show();
 98                 return;
 99             }
100             if (caculate() == true) {
101                 operator = inputText;
102                 showText = showText + "=" + result;
103                 tv_result.setText(showText);
104             } else {
105                 return;
106             }
107         } else if (resid == R.id.btn_plus || resid == R.id.btn_minus
108                 || resid == R.id.btn_multiply || resid == R.id.btn_divide ) {
109             if (firstNum.length() <= 0) {
110                 Toast.makeText(this, "请输入数字", Toast.LENGTH_SHORT).show();
111                 return;
112             }
113             if (operator.length() == 0 || operator.equals("=") == true
114                     || operator.equals("√") == true) {
115                 operator = inputText;// 操作符
116                 showText = showText + operator;
117                 tv_result.setText(showText);
118             } else {
119                 Toast.makeText(this, "请输入数字", Toast.LENGTH_SHORT).show();
120                 return;
121             }
122         } else if (resid == R.id.ib_sqrt) {
123             if (firstNum.length() <= 0) {
124                 Toast.makeText(this, "请输入数字", Toast.LENGTH_SHORT).show();
125                 return;
126             }
127             if (Double.parseDouble(firstNum) < 0) {
128                 Toast.makeText(this, "开根号的数值不能小于0", Toast.LENGTH_SHORT).show();
129                 return;
130             }
131             result = String.valueOf(Math.sqrt(Double.parseDouble(firstNum)));
132             firstNum = result;
133             nextNum = "";
134             operator = inputText;
135             showText = showText + "√=" + result;
136             tv_result.setText(showText);
137             Log.d(TAG, "result="+result+",firstNum="+firstNum+",operator="+operator);
138         } else {
139             if (operator.equals("=") == true) {
140                 operator = "";
141                 firstNum = "";
142                 showText = "";
143             }
144             if (resid == R.id.btn_dot) {
145                 inputText = ".";
146             }
147             if (operator.equals("") == true) {
148                 firstNum = firstNum + inputText;
149             } else {
150                 nextNum = nextNum + inputText;
151             }
152             showText = showText + inputText;
153             tv_result.setText(showText);
154         }
155         return;
156     }
157 
158     private String operator = ""; // 操作符
159     private String firstNum = ""; // 前一个操作数
160     private String nextNum = ""; // 后一个操作数
161     private String result = ""; // 当前的计算结果
162     private String showText = ""; // 显示的文本内容
163 
164     // 开始加减乘除四则运算
165     private boolean caculate() {
166         if (operator.equals("+") == true) {
167             result = String.valueOf(Arith.add(firstNum, nextNum));
168         } else if (operator.equals("-") == true) {
169             result = String.valueOf(Arith.sub(firstNum, nextNum));
170         } else if (operator.equals("×") == true) {
171             result = String.valueOf(Arith.mul(firstNum, nextNum));
172         } else if (operator.equals("÷") == true) {
173             if ("0".equals(nextNum)) {
174                 Toast.makeText(this, "被除数不能为零", Toast.LENGTH_SHORT).show();
175                 return false;
176             } else {
177                 result = String.valueOf(Arith.div(firstNum, nextNum));
178             }
179         }
180         firstNum = result;
181         nextNum = "";
182         return true;
183     }
184 
185     // 清空并初始化
186     private void clear(String text) {
187         showText = text;
188         tv_result.setText(showText);
189         operator = "";
190         firstNum = "";
191         nextNum = "";
192         result = "";
193     }
194 
195     public static void startHome(Context mContext) {
196         Intent intent = new Intent(mContext, class__2_5.class);
197         mContext.startActivity(intent);
198     }
199 
200 }

Arith

  1 package com.example.alimjan.hello_world;
  2 
  3 import java.math.BigDecimal;
  4 
  5 public class Arith {
  6     // 默认除法运算精度
  7     private static final int DEF_DIV_SCALE = 10;
  8 
  9     // 这个类不能实例化
 10     private Arith() {
 11         ;
 12     }
 13 
 14     /**
 15      * 提供精确的加法运算。
 16      * 
 17      * @param v1
 18      *            被加数
 19      * @param v2
 20      *            加数
 21      * @return 两个参数的和
 22      */
 23     public static String add(double v1, double v2) {
 24         BigDecimal b1 = new BigDecimal(Double.toString(v1));
 25         BigDecimal b2 = new BigDecimal(Double.toString(v2));
 26         return String.valueOf(b1.add(b2));
 27     }
 28 
 29     /**
 30      * 提供精确的加法运算。
 31      * 
 32      * @param v1
 33      *            被加数
 34      * @param v2
 35      *            加数
 36      * @return 两个参数的和
 37      */
 38     public static String add(String v1, String v2) {
 39         BigDecimal b1 = new BigDecimal(v1);
 40         BigDecimal b2 = new BigDecimal(v2);
 41         return String.valueOf(b1.add(b2));
 42     }
 43 
 44     /**
 45      * 提供精确的减法运算。
 46      * 
 47      * @param v1
 48      *            被减数
 49      * @param v2
 50      *            减数
 51      * @return 两个参数的差
 52      */
 53     public static String sub(double v1, double v2) {
 54         BigDecimal b1 = new BigDecimal(Double.toString(v1));
 55         BigDecimal b2 = new BigDecimal(Double.toString(v2));
 56         return String.valueOf(b1.subtract(b2));
 57     }
 58 
 59     /**
 60      * 提供精确的减法运算。
 61      * 
 62      * @param v1
 63      *            被减数
 64      * @param v2
 65      *            减数
 66      * @return 两个参数的差
 67      */
 68     public static String sub(String v1, String v2) {
 69         BigDecimal b1 = new BigDecimal(v1);
 70         BigDecimal b2 = new BigDecimal(v2);
 71         return String.valueOf(b1.subtract(b2));
 72     }
 73 
 74     /**
 75      * 提供精确的乘法运算。
 76      * 
 77      * @param v1
 78      *            被乘数
 79      * @param v2
 80      *            乘数
 81      * @return 两个参数的积
 82      */
 83     public static String mul(double v1, double v2) {
 84         BigDecimal b1 = new BigDecimal(Double.toString(v1));
 85         BigDecimal b2 = new BigDecimal(Double.toString(v2));
 86         return String.valueOf(b1.multiply(b2));
 87     }
 88 
 89     /**
 90      * 提供精确的乘法运算。
 91      * 
 92      * @param v1
 93      *            被乘数
 94      * @param v2
 95      *            乘数
 96      * @return 两个参数的积
 97      */
 98     public static String mul(String v1, String v2) {
 99         BigDecimal b1 = new BigDecimal(v1);
100         BigDecimal b2 = new BigDecimal(v2);
101         return String.valueOf(b1.multiply(b2));
102     }
103 
104     /**
105      * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
106      * 
107      * @param v1
108      *            被除数
109      * @param v2
110      *            除数
111      * @return 两个参数的商
112      */
113     public static String div(double v1, double v2) {
114         return div(v1, v2, DEF_DIV_SCALE);
115     }
116 
117     /**
118      * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
119      * 
120      * @param v1
121      *            被除数
122      * @param v2
123      *            除数
124      * @return 两个参数的商
125      */
126     public static String div(String v1, String v2) {
127         return div(v1, v2, DEF_DIV_SCALE);
128     }
129 
130     /**
131      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
132      * 
133      * @param v1
134      *            被除数
135      * @param v2
136      *            除数
137      * @param scale
138      *            表示表示需要精确到小数点以后几位。
139      * @return 两个参数的商
140      */
141     public static String div(double v1, double v2, int scale) {
142         if (scale < 0) {
143             throw new IllegalArgumentException(
144                     "The scale must be a positive integer or zero");
145         }
146         BigDecimal b1 = new BigDecimal(Double.toString(v1));
147         BigDecimal b2 = new BigDecimal(Double.toString(v2));
148         return String.valueOf(b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP));
149     }
150 
151     /**
152      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
153      * 
154      * @param v1
155      *            被除数
156      * @param v2
157      *            除数
158      * @param scale
159      *            表示表示需要精确到小数点以后几位。
160      * @return 两个参数的商
161      */
162     public static String div(String v1, String v2, int scale) {
163         if (scale < 0) {
164             throw new IllegalArgumentException(
165                     "The scale must be a positive integer or zero");
166         }
167         BigDecimal b1 = new BigDecimal(v1);
168         BigDecimal b2 = new BigDecimal(v2);
169 
170         BigDecimal result = null;
171         try {
172             result = b1.divide(b2);
173         } catch (Exception e) {
174             result = b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
175         }
176         return String.valueOf(result);
177     }
178 
179     /**
180      * 提供精确的小数位四舍五入处理。
181      * 
182      * @param v
183      *            需要四舍五入的数字
184      * @param scale
185      *            小数点后保留几位
186      * @return 四舍五入后的结果
187      */
188     public static String round(double v, int scale) {
189         if (scale < 0) {
190             throw new IllegalArgumentException(
191                     "The scale must be a positive integer or zero");
192         }
193         BigDecimal b = new BigDecimal(Double.toString(v));
194         BigDecimal one = new BigDecimal("1");
195         return String.valueOf(b.divide(one, scale, BigDecimal.ROUND_HALF_UP));
196     }
197 
198     /**
199      * 提供精确的小数位四舍五入处理。
200      * 
201      * @param v
202      *            需要四舍五入的数字
203      * @param scale
204      *            小数点后保留几位
205      * @return 四舍五入后的结果
206      */
207     public static String round(String v, int String, int scale) {
208         if (scale < 0) {
209             throw new IllegalArgumentException(
210                     "The scale must be a positive integer or zero");
211         }
212         BigDecimal b = new BigDecimal(v);
213         BigDecimal one = new BigDecimal("1");
214 
215         b.divide(one, scale, BigDecimal.ROUND_HALF_UP);
216 
217         return null;
218     }
219 }

 

Android 开发笔记___初级控件之实战__计算器