功能简单,实现并不难,对于初学者可以总和了解初级控件的基本使用。
用到的知识点如下:
- 线性布局 LinearLayout:整体界面是从上往下的,因此需要垂直方向的linearlayout;下面每行四个按钮,需要水平的linearlayout。
- 滚动视图 ScrollView :虽然界面不宽也不高,以防万一,有可能会遇到屏幕特别小的手机,因此用一个垂直方向的scrollview。
- 文本视图 TextView :上面标题就是一个textview,结果显示也是textview,但是更高级。能够从下往上滚动,前面的聊天室效果里用到过。
- 按钮 Button :下面的数字、运算符都是按钮。
- 图像视图 ImageView :未用到。
- 图像按钮 ImageButton :由于开根号运算符(√)虽然可以打出来,但是有点不一样,因此需要用到一个图像,就用到了图像按钮。
- 状态列表图形 :都有按下和弹起两种状态,因此订制了按钮的自定义样式。
- 形状图形 :运算结果用到的textview是一个圆角的矩形,所以定义了shape文件,把它作为文本视图的背景。
- 九宫格图片 :最下面的“0”按钮是有点大,因此需要两倍那么大的图片,如果使用普通的图片则会拉宽,效果很不好。因此就用到了。
style
<resources> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="btn_cal">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_weight">1</item>
<item name="android:gravity">center</item>
<item name="android:textColor">@color/black</item>
<item name="android:textSize">30sp</item>
<item name="android:background">@drawable/btn_nine_selector</item>
</style> </resources>
xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:gravity="top|center"
android:orientation="vertical"> <ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="简单计算器"
android:textColor="#000000"
android:textSize="22sp" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_white_with_stroke"
android:orientation="vertical"> <TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right|bottom"
android:lines="3"
android:maxLines="3"
android:scrollbars="vertical"
android:textColor="#000000"
android:textSize="25sp" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"> <Button
android:id="@+id/btn_cancel"
style="@style/btn_cal"
android:text="CE" /> <Button
android:id="@+id/btn_divide"
style="@style/btn_cal"
android:text="÷" /> <Button
android:id="@+id/btn_multiply"
style="@style/btn_cal"
android:text="×" /> <Button
android:id="@+id/btn_clear"
style="@style/btn_cal"
android:text="C" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"> <Button
android:id="@+id/btn_seven"
style="@style/btn_cal"
android:text="7" /> <Button
android:id="@+id/btn_eight"
style="@style/btn_cal"
android:text="8" /> <Button
android:id="@+id/btn_nine"
style="@style/btn_cal"
android:text="9" /> <Button
android:id="@+id/btn_plus"
style="@style/btn_cal"
android:text="+" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"> <Button
android:id="@+id/btn_four"
style="@style/btn_cal"
android:text="4" /> <Button
android:id="@+id/btn_five"
style="@style/btn_cal"
android:text="5" /> <Button
android:id="@+id/btn_six"
style="@style/btn_cal"
android:text="6" /> <Button
android:id="@+id/btn_minus"
style="@style/btn_cal"
android:text="-" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"> <Button
android:id="@+id/btn_one"
style="@style/btn_cal"
android:text="1" /> <Button
android:id="@+id/btn_two"
style="@style/btn_cal"
android:text="2" /> <Button
android:id="@+id/btn_three"
style="@style/btn_cal"
android:text="3" /> <ImageButton
android:id="@+id/ib_sqrt"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:scaleType="centerInside"
android:src="@drawable/sqrt"
android:background="@drawable/btn_nine_selector"/>
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"> <Button
android:id="@+id/btn_zero"
style="@style/btn_cal"
android:layout_weight="2"
android:text="0" /> <Button
android:id="@+id/btn_dot"
style="@style/btn_cal"
android:text="." /> <Button
android:id="@+id/btn_equal"
style="@style/btn_cal"
android:text="=" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView> </LinearLayout>
nineselec0tor
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/button_pressed" />
<item android:drawable="@drawable/button_normal" />
</selector>
putong
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/button_pressed_orig" />
<item android:drawable="@drawable/button_normal_orig" />
</selector>0
shape_oval
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" > <solid android:color="#ff66aa" /> <stroke
android:width="1dp"
android:color="#ffaaaaaa" /> </shape>
rect
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="#ffdd66" /> <stroke
android:width="1dp"
android:color="#ffaaaaaa" /> <corners
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp" /> </shape>
white_stroke
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="#ffffff" /> <stroke
android:width="1dp"
android:color="#bbbbbb" /> <corners
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp" /> </shape>
main
package com.example.alimjan.hello_world; import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable; /**
* Created by alimjan on 7/1/2017.
*/ import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast; import com.example.alimjan.hello_world.Arith; public class class__2_5 extends AppCompatActivity implements View.OnClickListener { private final static String TAG = "CalculatorActivity";
private TextView tv_result; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.code_2_5);
tv_result = (TextView) findViewById(R.id.tv_result);
tv_result.setMovementMethod(new ScrollingMovementMethod()); findViewById(R.id.btn_cancel).setOnClickListener(this);
findViewById(R.id.btn_divide).setOnClickListener(this);
findViewById(R.id.btn_multiply).setOnClickListener(this);
findViewById(R.id.btn_clear).setOnClickListener(this);
findViewById(R.id.btn_seven).setOnClickListener(this);
findViewById(R.id.btn_eight).setOnClickListener(this);
findViewById(R.id.btn_nine).setOnClickListener(this);
findViewById(R.id.btn_plus).setOnClickListener(this);
findViewById(R.id.btn_four).setOnClickListener(this);
findViewById(R.id.btn_five).setOnClickListener(this);
findViewById(R.id.btn_six).setOnClickListener(this);
findViewById(R.id.btn_minus).setOnClickListener(this);
findViewById(R.id.btn_one).setOnClickListener(this);
findViewById(R.id.btn_two).setOnClickListener(this);
findViewById(R.id.btn_three).setOnClickListener(this);
findViewById(R.id.btn_zero).setOnClickListener(this);
findViewById(R.id.btn_dot).setOnClickListener(this);
findViewById(R.id.btn_equal).setOnClickListener(this);
findViewById(R.id.ib_sqrt).setOnClickListener(this);
} @Override
public void onClick(View v) {
int resid = v.getId();
String inputText;
if (resid == R.id.ib_sqrt) {
inputText = "√";
} else {
inputText = ((TextView) v).getText().toString();
}
Log.d(TAG, "resid="+resid+",inputText="+inputText);
if (resid == R.id.btn_clear) {
clear("");
} else if (resid == R.id.btn_cancel) {
if (operator.equals("") == true) {
if (firstNum.length() == 1) {
firstNum = "0";
} else if (firstNum.length() > 0) {
firstNum = firstNum.substring(0, firstNum.length() - 1);
} else {
Toast.makeText(this, "没有可取消的数字了", Toast.LENGTH_SHORT).show();
return;
}
showText = firstNum;
tv_result.setText(showText);
} else {
if (nextNum.length() == 1) {
nextNum = "";
} else if (nextNum.length() > 0) {
nextNum = nextNum.substring(0, nextNum.length() - 1);
} else {
Toast.makeText(this, "没有可取消的数字了", Toast.LENGTH_SHORT).show();
return;
}
showText = showText.substring(0, showText.length() - 1);
tv_result.setText(showText);
}
} else if (resid == R.id.btn_equal) {
if (operator.length() == 0 || operator.equals("=") == true) {
Toast.makeText(this, "请输入运算符", Toast.LENGTH_SHORT).show();
return;
} else if (nextNum.length() <= 0) {
Toast.makeText(this, "请输入数字", Toast.LENGTH_SHORT).show();
return;
}
if (caculate() == true) {
operator = inputText;
showText = showText + "=" + result;
tv_result.setText(showText);
} else {
return;
}
} else if (resid == R.id.btn_plus || resid == R.id.btn_minus
|| resid == R.id.btn_multiply || resid == R.id.btn_divide ) {
if (firstNum.length() <= 0) {
Toast.makeText(this, "请输入数字", Toast.LENGTH_SHORT).show();
return;
}
if (operator.length() == 0 || operator.equals("=") == true
|| operator.equals("√") == true) {
operator = inputText;// 操作符
showText = showText + operator;
tv_result.setText(showText);
} else {
Toast.makeText(this, "请输入数字", Toast.LENGTH_SHORT).show();
return;
}
} else if (resid == R.id.ib_sqrt) {
if (firstNum.length() <= 0) {
Toast.makeText(this, "请输入数字", Toast.LENGTH_SHORT).show();
return;
}
if (Double.parseDouble(firstNum) < 0) {
Toast.makeText(this, "开根号的数值不能小于0", Toast.LENGTH_SHORT).show();
return;
}
result = String.valueOf(Math.sqrt(Double.parseDouble(firstNum)));
firstNum = result;
nextNum = "";
operator = inputText;
showText = showText + "√=" + result;
tv_result.setText(showText);
Log.d(TAG, "result="+result+",firstNum="+firstNum+",operator="+operator);
} else {
if (operator.equals("=") == true) {
operator = "";
firstNum = "";
showText = "";
}
if (resid == R.id.btn_dot) {
inputText = ".";
}
if (operator.equals("") == true) {
firstNum = firstNum + inputText;
} else {
nextNum = nextNum + inputText;
}
showText = showText + inputText;
tv_result.setText(showText);
}
return;
} private String operator = ""; // 操作符
private String firstNum = ""; // 前一个操作数
private String nextNum = ""; // 后一个操作数
private String result = ""; // 当前的计算结果
private String showText = ""; // 显示的文本内容 // 开始加减乘除四则运算
private boolean caculate() {
if (operator.equals("+") == true) {
result = String.valueOf(Arith.add(firstNum, nextNum));
} else if (operator.equals("-") == true) {
result = String.valueOf(Arith.sub(firstNum, nextNum));
} else if (operator.equals("×") == true) {
result = String.valueOf(Arith.mul(firstNum, nextNum));
} else if (operator.equals("÷") == true) {
if ("0".equals(nextNum)) {
Toast.makeText(this, "被除数不能为零", Toast.LENGTH_SHORT).show();
return false;
} else {
result = String.valueOf(Arith.div(firstNum, nextNum));
}
}
firstNum = result;
nextNum = "";
return true;
} // 清空并初始化
private void clear(String text) {
showText = text;
tv_result.setText(showText);
operator = "";
firstNum = "";
nextNum = "";
result = "";
} public static void startHome(Context mContext) {
Intent intent = new Intent(mContext, class__2_5.class);
mContext.startActivity(intent);
} }
Arith
package com.example.alimjan.hello_world; import java.math.BigDecimal; public class Arith {
// 默认除法运算精度
private static final int DEF_DIV_SCALE = 10; // 这个类不能实例化
private Arith() {
;
} /**
* 提供精确的加法运算。
*
* @param v1
* 被加数
* @param v2
* 加数
* @return 两个参数的和
*/
public static String add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return String.valueOf(b1.add(b2));
} /**
* 提供精确的加法运算。
*
* @param v1
* 被加数
* @param v2
* 加数
* @return 两个参数的和
*/
public static String add(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return String.valueOf(b1.add(b2));
} /**
* 提供精确的减法运算。
*
* @param v1
* 被减数
* @param v2
* 减数
* @return 两个参数的差
*/
public static String sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return String.valueOf(b1.subtract(b2));
} /**
* 提供精确的减法运算。
*
* @param v1
* 被减数
* @param v2
* 减数
* @return 两个参数的差
*/
public static String sub(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return String.valueOf(b1.subtract(b2));
} /**
* 提供精确的乘法运算。
*
* @param v1
* 被乘数
* @param v2
* 乘数
* @return 两个参数的积
*/
public static String mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return String.valueOf(b1.multiply(b2));
} /**
* 提供精确的乘法运算。
*
* @param v1
* 被乘数
* @param v2
* 乘数
* @return 两个参数的积
*/
public static String mul(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return String.valueOf(b1.multiply(b2));
} /**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 两个参数的商
*/
public static String div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
} /**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 两个参数的商
*/
public static String div(String v1, String v2) {
return div(v1, v2, DEF_DIV_SCALE);
} /**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @param scale
* 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static String div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return String.valueOf(b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP));
} /**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @param scale
* 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static String div(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2); BigDecimal result = null;
try {
result = b1.divide(b2);
} catch (Exception e) {
result = b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
}
return String.valueOf(result);
} /**
* 提供精确的小数位四舍五入处理。
*
* @param v
* 需要四舍五入的数字
* @param scale
* 小数点后保留几位
* @return 四舍五入后的结果
*/
public static String round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return String.valueOf(b.divide(one, scale, BigDecimal.ROUND_HALF_UP));
} /**
* 提供精确的小数位四舍五入处理。
*
* @param v
* 需要四舍五入的数字
* @param scale
* 小数点后保留几位
* @return 四舍五入后的结果
*/
public static String round(String v, int String, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(v);
BigDecimal one = new BigDecimal("1"); b.divide(one, scale, BigDecimal.ROUND_HALF_UP); return null;
}
}