用 Android Studio 从零开发一个多功能计算器应用

news2024/11/22 22:44:07

简介

计算器是每个学习 Android 开发者必经的经典项目之一。本篇文章将带你创建一个功能更强大的计算器应用,支持基本的加减乘除运算、带小数点的输入以及更多操作符功能。通过这个项目,你将全面掌握 Android 的布局设计、事件处理和逻辑实现技巧。


一、功能设计

基础功能
  1. 支持基本运算:加、减、乘、除。
  2. 支持小数点输入:可以输入和计算小数。
  3. 实时显示结果:输入数字和符号后立即显示计算结果。
进阶功能
  1. 清除功能:重置当前计算状态。
  2. 百分比运算:支持百分比的简单操作。
  3. 正负号切换:支持正负数输入。

二、项目创建与布局设计

1. 创建新项目
  • 打开 Android Studio,点击 New Project
  • 选择 Empty Activity 模板,命名项目为 AdvancedCalculator
  • 选择编程语言为 JavaKotlin
2. 布局设计

打开 res/layout/activity_main.xml 文件,设计用户界面。

完整布局代码:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <!-- 显示屏 -->
    <TextView
        android:id="@+id/tvDisplay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:padding="16dp"
        android:text="0"
        android:textSize="36sp"
        android:background="#E0E0E0"
        android:layout_marginBottom="16dp" />

    <!-- 按钮区域 -->
    <GridLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnCount="4"
        android:rowCount="5"
        android:padding="8dp">

        <!-- 第一行 -->
        <Button android:id="@+id/btnClear" android:text="C" style="@style/CalcButton"/>
        <Button android:id="@+id/btnSign" android:text="+/-" style="@style/CalcButton"/>
        <Button android:id="@+id/btnPercent" android:text="%" style="@style/CalcButton"/>
        <Button android:id="@+id/btnDivide" android:text="/" style="@style/CalcButton"/>

        <!-- 第二行 -->
        <Button android:id="@+id/btn7" android:text="7" style="@style/CalcButton"/>
        <Button android:id="@+id/btn8" android:text="8" style="@style/CalcButton"/>
        <Button android:id="@+id/btn9" android:text="9" style="@style/CalcButton"/>
        <Button android:id="@+id/btnMultiply" android:text="×" style="@style/CalcButton"/>

        <!-- 第三行 -->
        <Button android:id="@+id/btn4" android:text="4" style="@style/CalcButton"/>
        <Button android:id="@+id/btn5" android:text="5" style="@style/CalcButton"/>
        <Button android:id="@+id/btn6" android:text="6" style="@style/CalcButton"/>
        <Button android:id="@+id/btnSubtract" android:text="-" style="@style/CalcButton"/>

        <!-- 第四行 -->
        <Button android:id="@+id/btn1" android:text="1" style="@style/CalcButton"/>
        <Button android:id="@+id/btn2" android:text="2" style="@style/CalcButton"/>
        <Button android:id="@+id/btn3" android:text="3" style="@style/CalcButton"/>
        <Button android:id="@+id/btnAdd" android:text="+" style="@style/CalcButton"/>

        <!-- 第五行 -->
        <Button android:id="@+id/btn0" android:text="0" style="@style/CalcButton" android:layout_columnSpan="2"/>
        <Button android:id="@+id/btnDot" android:text="." style="@style/CalcButton"/>
        <Button android:id="@+id/btnEquals" android:text="=" style="@style/CalcButton"/>
    </GridLayout>
</LinearLayout>

样式:

<style name="CalcButton">
    <item name="android:layout_width">0dp</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_gravity">center</item>
    <item name="android:layout_weight">1</item>
    <item name="android:textSize">18sp</item>
    <item name="android:padding">16dp</item>
</style>

三、实现功能逻辑

1. 声明变量

MainActivity.java 中,定义需要的变量:

public class MainActivity extends AppCompatActivity {

    private TextView tvDisplay;
    private double firstOperand = 0;
    private double secondOperand = 0;
    private String operator = "";
    private boolean isNewInput = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvDisplay = findViewById(R.id.tvDisplay);
        setupListeners();
    }
}
2. 设置按钮监听事件

为每个按钮绑定点击事件:

private void setupListeners() {
    findViewById(R.id.btn0).setOnClickListener(v -> appendNumber("0"));
    findViewById(R.id.btn1).setOnClickListener(v -> appendNumber("1"));
    findViewById(R.id.btn2).setOnClickListener(v -> appendNumber("2"));
    findViewById(R.id.btn3).setOnClickListener(v -> appendNumber("3"));
    findViewById(R.id.btn4).setOnClickListener(v -> appendNumber("4"));
    findViewById(R.id.btn5).setOnClickListener(v -> appendNumber("5"));
    findViewById(R.id.btn6).setOnClickListener(v -> appendNumber("6"));
    findViewById(R.id.btn7).setOnClickListener(v -> appendNumber("7"));
    findViewById(R.id.btn8).setOnClickListener(v -> appendNumber("8"));
    findViewById(R.id.btn9).setOnClickListener(v -> appendNumber("9"));

    findViewById(R.id.btnAdd).setOnClickListener(v -> setOperator("+"));
    findViewById(R.id.btnSubtract).setOnClickListener(v -> setOperator("-"));
    findViewById(R.id.btnMultiply).setOnClickListener(v -> setOperator("*"));
    findViewById(R.id.btnDivide).setOnClickListener(v -> setOperator("/"));

    findViewById(R.id.btnDot).setOnClickListener(v -> appendNumber("."));
    findViewById(R.id.btnEquals).setOnClickListener(v -> calculate());
    findViewById(R.id.btnClear).setOnClickListener(v -> clearAll());
    findViewById(R.id.btnSign).setOnClickListener(v -> toggleSign());
    findViewById(R.id.btnPercent).setOnClickListener(v -> applyPercent());
}
3. 数字和操作符逻辑

数字输入:

private void appendNumber(String number) {
    if (isNewInput) {
        tvDisplay.setText("");
        isNewInput = false;
    }
    tvDisplay.append(number);
}

设置操作符:

private void setOperator(String op) {
    firstOperand = Double.parseDouble(tvDisplay.getText().toString());
    operator = op;
    isNewInput = true;
}
4. 计算结果
private void calculate() {
    secondOperand = Double.parseDouble(tvDisplay.getText().toString());
    double result = 0;

    switch (operator) {
        case "+":
            result = firstOperand + secondOperand;
            break;
        case "-":
            result = firstOperand - secondOperand;
            break;
        case "*":
            result = firstOperand * secondOperand;
            break;
        case "/":
            if (secondOperand != 0) {
                result = firstOperand / secondOperand;
            } else {
                tvDisplay.setText("Error");
                return;
            }
            break;
    }

    tvDisplay.setText(String.valueOf(result));
    isNewInput = true;
}
5. 清除功能
private void clearAll() {
    firstOperand = 0;
    secondOperand = 0;
    operator = "";
    tvDisplay.setText("0");
    isNewInput = true;
}
6. 其他功能

百分比:

private void applyPercent() {
    double current = Double.parseDouble(tvDisplay.getText().toString());
    tvDisplay.setText(String.valueOf(current / 100));
    isNewInput = true;
}

**正负号

切换:**

private void toggleSign() {
    double current = Double.parseDouble(tvDisplay.getText().toString());
    tvDisplay.setText(String.valueOf(-current));
}

四、运行与测试

  1. 运行项目
    点击 Android Studio 的 Run 按钮,在模拟器或真实设备上测试应用。

  2. 测试功能
    验证加减乘除、百分比、正负切换等功能是否正确。


五、总结

通过本文的项目开发,你学习了以下内容:

  1. 使用 Android Studio 创建用户界面。
  2. 在 Android 中处理按钮点击事件。
  3. 实现计算器的核心逻辑,包括实时计算和错误处理。

扩展这个项目,你可以添加更多高级功能,如历史记录、科学计算模式等。继续尝试,相信你会开发出更复杂、更实用的应用!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2245595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker3:docker基础1

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

《Django 5 By Example》阅读笔记:p645-p650

《Django 5 By Example》学习第8天&#xff0c;p645-p650总结&#xff0c;总计6页。 一、技术总结 1.django-rest-framework (1)serializer p648, Serializer: Provides serialization for normal Python class instances。Serializer又细分为Serializer, ModelSerializer,…

【机器学习】回归模型(线性回归+逻辑回归)原理详解

线性回归 Linear Regression 1 概述 线性回归类似高中的线性规划题目。线性回归要做的是就是找到一个数学公式能相对较完美地把所有自变量组合&#xff08;加减乘除&#xff09;起来&#xff0c;得到的结果和目标接近。 线性回归分为一元线性回归和多元线性回归。 2 一元线…

【大模型推理】vLLM 源码学习

强烈推荐 https://zhuanlan.zhihu.com/p/680153425 sequnceGroup 存储了相同的prompt对应的不同的sequence, 所以用字典存储 同一个Sequence可能占据多个逻辑Block&#xff0c; 所以在Sequence 中用列表存储 同一个block 要维护tokens_id 列表, 需要添加操作。 还需要判断blo…

FIFO和LRU算法实现操作系统中主存管理

FIFO&#xff0c;用数组实现 1和2都是使用nextReplace实现新页面位置的更新 1、不精确时间&#xff1a;用ctime输出运行时间都是0.00秒 #include <iostream> #include <iomanip> #include<ctime>//用于计算时间 using namespace std;// 页访问顺序 int pa…

【Ubuntu24.04】VirtualBox安装ubuntu-live-server24.04

目录 0 背景1 下载镜像2 安装虚拟机3 安装UbuntuServer24.044 配置基本环境5 总结0 背景 有了远程连接工具之后,似乎作为服务器的Ubuntu24.04桌面版有点备受冷落了,桌面版的Ubuntu24.04的优势是图形化桌面,是作为一个日常工作的系统来用的,就像Windows,如果要作为服务器来…

《SpringBoot、Vue 组装exe与套壳保姆级教学》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

Flowable第一篇、快速上手(Flowable安装、配置、集成)

目录 Flowable 概述Flowable的安装与配置 2.1. FlowableUI安装 2.2. Flowable BPMN插件下载 2.3 集成Spring Boot流程审核操作 3.3 简单流程部署 3.4 启动流程实例 3.5 流程审批 一、Flowable 概述 Flowable是一个轻量级、高效可扩展的工作流和业务流程管理&#xff08;BPM&…

Docker搭建有UI的私有镜像仓库

Docker搭建有UI的私有镜像仓库 一、使用这个docker-compose.yml文件&#xff1a; version: 3services:registry-ui:image: joxit/docker-registry-ui:2.5.7-debianrestart: alwaysports:- 81:80environment:- SINGLE_REGISTRYtrue- REGISTRY_TITLEAtt Docker Registry UI- DE…

容器安全检测和渗透测试工具

《Java代码审计》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484219&idx1&sn73564e316a4c9794019f15dd6b3ba9f6&chksmc0e47a67f793f371e9f6a4fbc06e7929cb1480b7320fae34c32563307df3a28aca49d1a4addd&scene21#wechat_redirect Docker-bench-…

Day10_CSS过度动画

Day10_CSS过度动画 背景 : PC和APP项目我们已经开发完毕, 但是再真正开发的时候有些有些简易的动态效果我们可以使用CSS完成 ; 本节课我们来使用CSS完成基础的动画效果 今日学习目标 CSS3过度CSS3平面动态效果CSS3动画效果案例 1. CSS3过渡 ​ 含义 :过渡指的是元素从一种…

iOS应用网络安全之HTTPS

移动互联网开发中iOS应用的网络安全问题往往被大部分开发者忽略, iOS9和OS X 10.11开始Apple也默认提高了安全配置和要求. 本文以iOS平台App开发中对后台数据接口的安全通信进行解析和加固方法的分析. 1. HTTPS/SSL的基本原理 安全套接字层 (Secure Socket Layer, SSL) 是用来…

excel版数独游戏(已完成)

前段时间一个朋友帮那小孩解数独游戏&#xff0c;让我帮解&#xff0c;我看他用电子表格做&#xff0c;只能显示&#xff0c;不能显示重复&#xff0c;也没有协助解题功能&#xff0c;于是我说帮你做个电子表格版的“解题助手”吧&#xff0c;不能直接解题&#xff0c;但该有的…

金融数据中心容灾“大咖说” | 美创科技赋能“灾备一体化”建设

中国人民银行发布的《金融数据中心容灾建设指引》&#xff08;JR/T 0264—2024&#xff09;已于2024年7月29日正式实施。这一金融行业标准对金融数据中心容灾建设中的“组织保障、需求分析、体系规划、建设要求、运维管理”进行了规范和指导。面对不断增加的各类网络、业务、应…

Qt:信号槽

一. 信号槽概念 信号槽 是 Qt 框架中一种用于对象间通信的机制 。它通过让一个对象发出信号&#xff0c;另一个对象连接到这个信号的槽上来实现通信。信号槽机制是 Qt 的核心特性之一&#xff0c;提供了一种灵活且类型安全的方式来处理事件和数据传递。 1. 信号的本质 QT中&a…

SpringBoot与MongoDB深度整合及应用案例

SpringBoot与MongoDB深度整合及应用案例 在当今快速发展的软件开发领域&#xff0c;NoSQL数据库因其灵活性和可扩展性而变得越来越流行。MongoDB&#xff0c;作为一款领先的NoSQL数据库&#xff0c;以其文档导向的存储模型和强大的查询能力脱颖而出。本文将为您提供一个全方位…

大数据调度组件之Apache DolphinScheduler

Apache DolphinScheduler 是一个分布式易扩展的可视化 DAG 工作流任务调度系统。致力于解决数据处理流程中错综复杂的依赖关系&#xff0c;使调度系统在数据处理流程中开箱即用。 主要特性 易于部署&#xff0c;提供四种部署方式&#xff0c;包括Standalone、Cluster、Docker和…

ThinkPHP6门面(Facade)

门面 门面&#xff08;Facade&#xff09; 门面为容器中的&#xff08;动态&#xff09;类提供了一个静态调用接口&#xff0c;相比于传统的静态方法调用&#xff0c; 带来了更好的可测试性和扩展性&#xff0c;你可以为任何的非静态类库定义一个facade类。 系统已经为大部分…

MySQL win安装 和 pymysql使用示例

目录 一、MySQL安装 下载压缩包&#xff1a; 编写配置文件&#xff1a; 配置环境变量&#xff1a; 初始化服务和账户 关闭mysql开机自启&#xff08;可选&#xff09; 建议找一个数据库可视化软件 二、使用pymysql操作数据库 安装pymysql 示例代码 报错处理 一、My…

Parker派克防爆电机在实际应用中的安全性能如何保证?

Parker防爆电机确保在实际应用中的安全性能主要通过以下几个方面来保证&#xff1a; 1.防爆外壳设计&#xff1a;EX系列电机采用强大的防爆外壳&#xff0c;设计遵循严格的防爆标准&#xff0c;能够承受内部可能发生的爆炸而不破损&#xff0c;利用间隙切断原理&#xff0c;防…