简介:这是一份基于Android Studio开发的简易计算器期末大作业,面向K12阶段初学Android的学生,完整覆盖了从界面布局、事件监听、计算逻辑到测试打包的典型开发流程。项目采用Empty Activity模板,包含数字与运算符按钮、结果显示区,并通过栈数据结构处理运算符优先级,兼顾了基础功能与计算机科学概念,适合作为安卓课程设计、结课作业或入门练手的参考样例。压缩包共48个文件,主要包含12张png图片(界面效果与图标)、11个xml布局及资源文件、3个java源代码文件,以及gradle构建脚本、属性配置等,整体仅180KB,结构轻量、打开即可对照学习。目前已有4326人学习下载。通过这份资源,可以拿到可直接运行的计算器工程源码、清晰的目录结构和完整的Android项目配置,能够帮助理解Activity、XML布局、事件监听与业务逻辑分离等核心知识点,也可在此基础上扩展功能或修改界面风格,快速完成个人作业。 期末大作业这东西,很多同学都是拖到最后一周才开始动手。如果你正在为“Android Studio 简易计算器”发愁,这篇文章应该能帮你把思路彻底理清楚——从界面布局到逻辑实现,再到真机调试的坑,我会按自己带项目时习惯的顺序,把一套能直接拿去交作业的完整方案拆开讲透。不管你是刚装好 Android Studio、连模拟器都还没跑起来的新手,还是已经写完基础功能想让界面更像样一点的进阶党,这篇都值得看完。
1. 项目整体设计与需求梳理
1.1 先想清楚“简易计算器”到底要做什么
很多同学拿到这个题目就开始写代码,结果写到一半发现逻辑越写越乱。我建议第一步不是打开 Android Studio,而是拿张纸把这个计算器的功能边界画出来。期末大作业的“简易计算器”,通常只需要支持加减乘除、小数点和清零这四类操作,再加上一个等号键计算结果,就已经能拿到不错的分数了。更进一步的话,可以加正负号切换、退格键、连续运算,甚至简单的括号支持——但每加一个功能,逻辑复杂度都是成倍增长的。
我的建议是:第一版只做标准功能,确保跑通,然后看剩余时间再决定要不要往上加特性。大作业最怕的是功能没做完、程序崩溃,而不是功能不够新。
1.2 选对布局方案,能让你的作业看起来贵一半
计算器界面是所有安卓界面里最适合练布局的题目,因为它的按键分布天然就是网格结构。常见的做法有三种:
第一种是用多个LinearLayout一层一层嵌套,每行五个按钮这样的结构。代码写起来很啰嗦,而且不同屏幕尺寸的适配效果很差,不建议花时间在这上面。
第二种是单行滚动的HorizontalScrollView套按钮,这个更不适合计算器,属于方向性错误。
第三种就是用GridLayout,直接在布局文件里声明行和列,代码最简洁,每行几个按钮一目了然。配合layout_columnWeight让每个按钮均匀拉伸,在手机、平板上的表现都稳定,这也是我现在最推荐大家采用的方式。
1.3 前后端分离,别把逻辑全塞进 MainActivity
这个观念我觉得越早建立越好。所谓“前后端分离”不是说让你用 MVVM 或者 Jetpack Compose,而是在写代码时就把“界面怎么显示”和“数据怎么算”这两件事分开。
具体到计算器这个小项目里,就是 MainActivity 只负责绑定控件、设置按钮点击事件、把结果显示到界面上;计算逻辑单独抽一个CalculatorLogic类来管理,里面处理好数字输入、操作符记录、等号计算这些状态转换。这样做的好处一个是代码结构好看,评分老师翻阅时印象分会高;另一个是你改界面或者修计算 bug 时不需要从头读到尾,定位问题的速度快很多。
2. 计算器界面搭建实战
2.1 布局文件的骨架:从显示区到按键区
一个经典的计算器界面从功能上分两大块:上面是显示区,放当前输入的数字和运算结果;下面是按键区,排列数字、操作符和功能键。
显示区我用一块TextView来做,把layout_width设置成match_parent,高度给一个自适应数值,比如 120dp 左右,背景色可以用深色,文字设置成白色,gravity使用end|bottom让数字右对齐并贴在底部,这样看起来跟真机计算器的视觉风格很接近。字号方面建议用sp单位,比如 42sp,避免用固定dp。
按键区我强烈建议用GridLayout来组织,列数设为 4。如果你的功能只有加减乘除、等号、C、小数点、正负号和退格,那 4 列 5 行刚好装得下。每行第一个按钮放数字 7、8、9 这种顺序,和系统计算器的键位保持一致,评分老师一上手就会觉得顺手。
2.2 按键样式的统一处理
很多同学的按钮默认是系统那个灰色小方块,颜色单调、按压反馈也不明显,看起来就很“大作业”。其实不用写任何额外代码,在res/drawable下新建一个 XML 文件,比如button_bg.xml,用shape定义圆角和背景色,再用selector区分默认状态和按下状态的背景色,就能让所有按钮的质感提升一大截。
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <shape android:shape="rectangle"> <solid android:color="#FF666666" /> <corners android:radius="8dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <solid android:color="#FF3C3C3C" /> <corners android:radius="8dp" /> </shape> </item> </selector>注意按压状态的颜色比默认颜色亮一些,这样手指按上去会有“按钮沉下去”的反馈。给所有按钮统一设置android:background="@drawable/button_bg",再统一配置文字颜色和字号,整个界面的完成度就上来了。
2.3 显示区的补充设计
代码运行后你会发现一个问题:输入超长数字时,TextView文字会溢出边界或者被截断。处理办法是设置android:maxLines="1",然后配合android:autoSizeTextType="uniform",这行属性可以让文字在超过控件宽度时自动缩小字号,效果非常自然。想完全自己控制缩放逻辑的话,也可以在代码里监听文字长度动态改字号,但期末阶段没必要写那么复杂,系统自带的自适应就够用了。
3. 计算逻辑的实现与避坑
3.1 为什么不能用“把所有内容拼成字符串再解析”
计算器逻辑的第一版方案很多人都想到过:把用户按下的数字和符号全部累积成一个字符串,按等号时用String拼接成一个完整的数学表达式,然后扔给一个计算引擎去解析求值。
这个方案在最简单的两级运算(比如12+3)里没问题,但一旦出现连续运算就比较麻烦了。比如用户输入2+3×4,按字符串解析的结果顺序算出来是(2+3)×4=20,而正确的数学规则是先乘除后加减,结果是14。要处理运算符优先级,字符串解析的逻辑复杂度会瞬间翻倍。
所以计算器逻辑实现上,我的建议是放弃“全字符串解析型”,改用更符合直觉的“边输入边计算”状态机方案。
3.2 状态机的核心概念:当前值、上一值、待定操作符
所谓“边输入边计算”,本质上是维护三个关键数据:
currentInput:用户当前正在输入的数字previousValue:上一个参与计算的数字pendingOperator:等待执行的操作符
用这个状态机来解释用户操作流程,会变得非常清晰:
- 用户按
1、2、3,你在currentInput后面追加数字,屏幕显示123。 - 用户按
+,你把currentInput保存到previousValue,把操作符+存入pendingOperator,然后把currentInput清零,等待输入第二个操作数。 - 用户按
4、5,currentInput变成45。 - 用户按
=,执行previousValue + currentInput,结果168,把结果写回previousValue,显示出来,同时清空pendingOperator。
如果用户在状态 4 之后继续按+和6再按等号,则拿当前显示结果168当作上一值,继续参与下一轮运算。这个设计天然支持“连续运算”功能,而且不会因为精度问题出现浮点数误差累积。
3.3 小数点和正负号的处理细节
小数点的逻辑有个常见 bug:用户按完0再按.,如果你的代码里写的是“末尾追加”,屏幕会显示成0.,这是没问题的。但如果用户继续按.,第二次按下应该被忽略,否则会出现0..这种非法数字。
正负号切换我建议在currentInput前加负号实现,并且顺序要处理对:如果用户正在输入一个数字,切换成负数;再次按下则去掉负号。如果你用的是StringBuilder,检查首位字符是不是-,是就删掉,不是就插入到开头,然后刷新显示。
小数点在往currentInput追加时,还要先判断currentInput里面是否已经有了小数点,如果有就直接忽略本次按钮事件,这样就能避免非法输入。
3.4 用 BigDecimal 解决浮点精度问题
如果你直接使用double类型做计算,0.1+0.2的结果会显示成0.30000000000000004,这个问题在计算器里是没法忍受的。解决方案是用BigDecimal来做最终运算。
private String calculate(double v1, double v2, char op) { BigDecimal bd1 = BigDecimal.valueOf(v1); BigDecimal bd2 = BigDecimal.valueOf(v2); switch (op) { case '+': return bd1.add(bd2).stripTrailingZeros().toPlainString(); case '-': return bd1.subtract(bd2).stripTrailingZeros().toPlainString(); case '*': return bd1.multiply(bd2).stripTrailingZeros().toPlainString(); case '/': if (bd2.compareTo(BigDecimal.ZERO) == 0) { return "错误"; } return bd1.divide(bd2, 10, RoundingMode.HALF_UP) .stripTrailingZeros().toPlainString(); default: return "0"; } }注意stripTrailingZeros()的作用是把10.0转换成10,避免界面上出现多余的小数位;toPlainString()则是为了避免超大数或极小数的科学计数法显示。除零检查是必写的,返回一个“错误”字符串,同时要设置好标志位防止后续输入误操作。
3.5 连续运算时“等号连按”的行为设计
还有一种高频需求:计算完一次结果后,用户继续按=,期望上一次运算自动重复执行。比如先输入10+5得到15,再按一次=,期望得到20。
这个功能是在状态机基础上加一个lastOperator和lastOperand来记录上一次的操作符和操作数,等号被再次触发时复用这两份记录就可以了。这个特性属于“加分项”,实现成本低而且演示效果明显,建议有余力的同学加上。
3.6 按钮监听的最简注册方式
给十几个按钮写findViewById加setOnClickListener其实很冗余,Android 提供了更简洁的写法:在布局文件里给每个按钮加android:onClick="onButtonClick",然后在 Activity 里写一个统一方法:
public void onButtonClick(View view) { Button btn = (Button) view; String text = btn.getText().toString(); switch (text) { case "C": reset(); break; case "=": onEquals(); break; case "+": case "-": case "×": case "÷": onOperator(text.charAt(0)); break; default: onNumberInput(text); break; } }这个方案看似取巧,但对于期末大作业这种场景是合理的,能让代码量骤减。但要提醒一句:不要在text里直接写“×”和“÷”的原始符号,界面显示用的符号和逻辑存储用的符号最好分离,否则你会被迫在onOperator里做一层映射转换。
4. Android Studio 环境配置与真机调试
4.1 新建项目老是卡在 Gradle 下载怎么办
那批和 Android Studio 安装、Gradle 下载相关的搜索热词,其实透露出很多同学在环境阶段就被劝退了。Android Studio 每次新建项目都要下载 Gradle,这本质上是项目构建工具要拉取不同版本的依赖,网络不稳定就会卡很久。
我的经验是:先手动下载一个能用的 Gradle 版本,然后在gradle-wrapper.properties文件里把distributionUrl改成file:///开头的本地路径,从此新建任何项目都会直接读取本地文件,不会再因为网络问题卡住。
具体步骤:先看自己 Android Studio 版本对应的推荐 Gradle 版本,去官网下载 zip 包解压到D:\gradle之类的目录,然后修改每个项目的gradle/wrapper/gradle-wrapper.properties文件:
distributionUrl=file:///D:/gradle/gradle-8.7-bin.zip这样配置后,项目的 Gradle 构建速度会显著提升,从源头杜绝了“新建项目就要下载半小时”的问题。
4.2 模拟器跑不动,真机调试如何连接
如果你的电脑配置不高,Android Studio 自带的模拟器会很卡,这时候用真机调试效率更高。搜索热词里“Android Studio 如何连接小米手机”这类问题相当高频,其实核心就三步。
第一步,在 Android 手机的“设置”里连续点击“版本号”7 次,打开开发者模式;第二步,在开发者选项里打开“USB 调试”和“USB 安装”;第三步,用数据线把手机连到电脑,手机弹窗里选择“允许 USB 调试”。
之后 Android Studio 顶部工具栏的设备下拉框里就会出现你的手机型号。需要注意的是小米、华为等部分机型需要额外打开“USB 安装(通过 USB 安装应用)”,否则跑项目时手机会弹窗提示未知来源,点击允许就行。
4.3 中文乱码与界面显示异常处理
有些同学的 Android Studio 界面是英文的,去搜索“怎么设置中文”其实不需要额外操作。Android Studio 的汉化需要通过插件市场安装 Chinese Language Pack,安装后重启即可。这里提醒一句:汉化只影响 IDE 界面,不影响你写的程序,随便装。
另外如果你的项目里出现了TextView显示中文乱码,检查一下res/values/strings.xml里的编码是不是被改成了非 UTF-8,以及是不是直接在layout里硬编码了中文而没有走资源文件。
5. 常见问题与排查技巧实录
5.1 按钮没有反应,点击后什么也不发生
这个问题在真机调试里特别常见,十有八九是Button的onClick方法在XML里配了,但 Activity 里没有对应方法,或者方法签名写错。常规排查思路是:先给onButtonClick加一行Log.d("Calculator", "onClick: " + text);,看 Logcat 里有没有输出。没有日志就是监听没挂上,有日志但界面没变化就是显示逻辑的问题。Logcat 是 Android 调试的通用手段,比“瞎猜按钮怎么写”要高效得多。
5.2 等号算完结果后,继续按数字会把新数字拼在老结果后面
这是状态机设计不完整导致的典型问题:计算结果后应该把previousValue清空、currentInput设为结果字符串,而不是还停留在“上一次输入”的状态。在onEquals里最后加一句isResultDisplayed = true;,然后在onNumberInput开头的逻辑里判断这个标志位:
if (isResultDisplayed) { currentInput = ""; isResultDisplayed = false; }这样每次按数字键时会先清空旧结果显示区,然后正常输入新数字,逻辑就正确了。
5.3 一按等号程序就闪退
期末代码最常见的崩因是空指针:currentInput为空字符串时去做Double.parseDouble,抛了NumberFormatException。我的建议是给所有数字解析操作加一层防护:先判断字符串是否为空、是否为合法数字格式,为空或非法时直接返回 0,或者弹 Toast 提示“输入不完整”,而不是让程序崩溃。
除零同样要防护,前面代码里已经写了compareTo判断,很多同学只判断v2 == 0,在double类型下除零不会崩溃只会得到Infinity,但显示成 Infinity 也很不专业,还是建议统一处理成“错误”。
5.4 快速连续按等号导致计算顺序错乱
快速连按=时,如果lastOperand还没被正确保存,计算顺序就会错乱。解决办法是让lastOperand在每次按下操作符并输入完第二个操作数后再更新。具体来说,onEquals逻辑里有一个分支是“重复上一次运算”,此时使用lastOperand作为第二操作数;另一个分支是“执行当前输入”,此时使用currentInput作为第二操作数,同时更新lastOperand。
5.5 实用排查速查表
| 问题现象 | 常见原因 | 排查思路 |
|---|---|---|
| 按钮点击无反应 | XML 里 onClick 方法名写错或方法签名不对 | 查看 Logcat 是否有日志输出 |
| 计算结果保留多位小数 | 使用了 double 直接运算 | 改用 BigDecimal 并 stripTrailingZeros |
| 界面在中文系统下显示方块 | 布局里硬编码了中文字符但没有正确编码 | 把文案移到 strings.xml 并用资源引用 |
| 模拟器加载极慢 | 电脑配置低或模拟器镜像不兼容 | 换成真机调试,开启开发者模式 |
| 真机安装不上应用 | USB 安装权限未开启 | 打开开发者选项里的 USB 安装开关 |
6. 结项提交与答辩准备的加分建议
最后再分享一个很多人忽略的点。期末大作业要交的不只是代码,通常还要写一份说明文档或做演示视频。我的经验是,除了把功能展示清楚,一定要在文档里放一张状态机设计图或者逻辑流程图,哪怕手绘都行,这能让老师瞬间看出你的思路是有设计的,而不只是照着网上代码抄。
答辩时如果老师问你“为什么用 BigDecimal”,你能答出“浮点数有精度问题,计算器结果要精确”,这就是一个很清晰的技术亮点。平时写代码的时候多问自己一句“为什么这么写”,积累下来就是你面试时能讲的实战故事。
这个项目看起来简单,但如果你真的动手把状态机捋顺了、把界面细节打磨好了、把异常情况都考虑到了,它就远远不止是一门课的作业而已——很多基础扎实的开发者,都是从第一个“能用的东西”开始的。
本文还有配套的精品资源,点击获取