目录
[1. 基础开发环境](#1. 基础开发环境)
[2. 计算器的布局和相关按钮](#2. 计算器的布局和相关按钮)
[3. 计算器的主要运算逻辑](#3. 计算器的主要运算逻辑)
[4. APK 文件](#4. APK 文件)
[5. 项目源码](#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">
<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="match_parent"
android:gravity="center"
android:text="@string/simple_calculator"
android:textColor="@color/black"
android:textSize="20sp"/>
<TextView
android: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"/>
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="4"
android:rowCount="5">
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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"/>
<Button
android: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 = "";
@Override
protected 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);
}
@Override
public 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 文件见文件开头,可直接下载安装。