目录
1. 基础开发环境
2. 计算器的布局和相关按钮
3. 计算器的主要运算逻辑
4. APK 文件
5. 项目源码
1. 基础开发环境
JDK:JDK17
Android Studio:Android Studio Giraffe | 2022.3.1
Android SDK:Android API 34
Gradle: gradle-8.0-bin.zip
2. 计算器的布局和相关按钮
使用 LinearLayout 和 GridLayout 实现计算器的交互前端。
layout 文件如下
<?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:background="#EEEEEE"android:orientation="vertical"android:padding="5dp"><ScrollViewandroid:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="@string/simple_calculator"android:textColor="@color/black"android:textSize="20sp"/><TextViewandroid:id="@+id/tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/white"android:lines="3"android:text="@string/filler"android:gravity="end|bottom"android:textColor="@color/black"android:textSize="25sp"/><GridLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:columnCount="4"android:rowCount="5"><Buttonandroid:id="@+id/btn_clear_entry"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/cancel"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_divide"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/divide"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_multiply"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/multiply"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_clear"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/delete"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_seven"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/seven"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_eight"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/eight"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_nine"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/nine"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_plus"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/plus"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_four"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/four"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_five"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/five"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_six"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/six"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_minus"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/minus"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_one"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/one"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_two"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/two"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_three"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/three"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_sqrt"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/sqrt"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_reciprocal"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/reciprocal"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_zero"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/zero"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_dot"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/dot"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/><Buttonandroid:id="@+id/btn_equal"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:layout_columnWeight="1"android:gravity="center"android:text="@string/equal"android:textColor="@color/black"android:textSize="@dimen/button_font_size"/></GridLayout></LinearLayout></ScrollView></LinearLayout>
相关 values 如下:
- strings.xml
<resources><string name="app_name">calculator</string><string name="simple_calculator">计算器</string><string name="filler">0</string><string name="cancel">CE</string><string name="divide">÷</string><string name="multiply">×</string><string name="plus">+</string><string name="minus">-</string><string name="delete">C</string><string name="zero">0</string><string name="one">1</string><string name="two">2</string><string name="three">3</string><string name="four">4</string><string name="five">5</string><string name="six">6</string><string name="seven">7</string><string name="eight">8</string><string name="nine">9</string><string name="sqrt">√</string><string name="dot">.</string><string name="equal">=</string><string name="reciprocal">1/X</string>
</resources>
- dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="button_font_size">30sp</dimen><dimen name="button_height">75dp</dimen>
</resources>
实际效果:
3. 计算器的主要运算逻辑
package com.example.calculator;import android.os.Bundle;
import android.view.View;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import java.util.Arrays;
import java.util.List;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private TextView tvResult;private String firstNum = "";private String secondNum = "";private String operator = "";private String result = "";private String showText = "";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 从布局文件中获取文本视图tvResult = findViewById(R.id.tv_result);// 为所有按钮注册点击监听器findViewById(R.id.btn_clear_entry).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_sqrt).setOnClickListener(this);findViewById(R.id.btn_reciprocal).setOnClickListener(this);findViewById(R.id.btn_zero).setOnClickListener(this);findViewById(R.id.btn_dot).setOnClickListener(this);findViewById(R.id.btn_equal).setOnClickListener(this);}@Overridepublic void onClick(View view) {String inputText = ((TextView) view).getText().toString();List<Integer> fourOperations = Arrays.asList(R.id.btn_plus, R.id.btn_minus, R.id.btn_multiply, R.id.btn_divide);int id = view.getId();if (id == R.id.btn_clear) {// 清除clear();} else if (id == R.id.btn_clear_entry) {// 清除输入clearEntryOperate();} else if (fourOperations.contains(id)) {operator = inputText;refreshShowText(showText + operator);// 四则运算} else if (id == R.id.btn_equal) {// 等号if (!secondNum.equals("")) {double calculateResult = calculateFour();refreshOperateResult(String.valueOf(calculateResult));refreshShowText(result);}} else if (id == R.id.btn_sqrt) {// 根号double sqrtResult = Math.sqrt(Double.parseDouble(firstNum));refreshOperateResult(String.valueOf(sqrtResult));refreshShowText(result);} else if (id == R.id.btn_reciprocal) {// 倒数double reciprocalResult = 1.0 / Double.parseDouble(firstNum);refreshOperateResult(String.valueOf(reciprocalResult));refreshShowText(result);} else {// 其它if (result.length() > 0 && operator.equals("")) {clear();}if (operator.equals("")) {firstNum += inputText;} else {secondNum += inputText;}if (showText.equals("0") && !inputText.equals(".")) {refreshShowText(inputText);} else {refreshShowText(showText + inputText);}}}private double calculateFour() {switch (operator) {case "+":return Double.parseDouble(firstNum) + Double.parseDouble(secondNum);case "-":return Double.parseDouble(firstNum) - Double.parseDouble(secondNum);case "×":return Double.parseDouble(firstNum) * Double.parseDouble(secondNum);default:return Double.parseDouble(firstNum) / Double.parseDouble(secondNum);}}private void clear() {refreshOperateResult("");refreshShowText("0");}private void refreshOperateResult(String newResult) {result = newResult;firstNum = result;secondNum = "";operator = "";}private void clearEntryOperate() {String tmp = showText.substring(0, showText.length() - 1);if (tmp.equals("")) {tmp = "0";}refreshShowText(tmp);}// 刷新显示文本private void refreshShowText(String text) {showText = text;integerRemoveDot();tvResult.setText(showText);}private void integerRemoveDot() {int start = showText.indexOf(".");if (start != -1) {int end = showText.length();String value = showText.substring(start + 1, end);if (Double.parseDouble(value) == 0.0) {showText = showText.substring(0, start);}}}
}
4. APK 文件
构建好的 APK 文件见文件开头,可直接下载安装。
5. 项目源码
https://gitee.com/hl0929/calculator