• Android 实战项目:简单计算器



    实战项目:简易计算器

    1.需求分析

    虽然只学了一些Android的简单控件,但是只要活学善用这些布局和控件,也能够做出实用的App。

    接下来让我们尝试设计并实现一个简单计算器。

    2.界面设计

    Windows计算器,它主要由上半部分的计算结果与下半部分的计算按钮两块区域组成,据此可创建一个界面相似的计算器App,同样由计算结果和计算按钮两部分组成,如下图所示。
    在这里插入图片描述
    下面是设计的简易计算器效果图。
    在这里插入图片描述

    按照计算器App的效果图,大致分布着下列Android控件:

    • 线性布局LinearLayout:因为计算器界面整体从上往下布局,所以需要垂直方向的LinearLayout。
    • 网格布局GridLayout:计算器下半部分的几排按钮,正好成五行四列表格分布,适合采用GridLayout。
    • 滚动视图ScrollView:虽然计算器界面不宽也不高,但是以防万一,最好还是加个垂直方向的ScrollView。
    • 文本视图TextView:很明显顶部标题“简单计算器”就是TextView,且文字居中显示;标题下面的计算结果也需要使用TextView,且文字靠右靠下显示。
    • 按钮Button:几乎所有的数字与运算符按钮都采用了Button控件。
    • 图像按钮ImageButton:开根号的运算符“√”虽然能够打出来,但是右上角少了数学课本上的一横,所以该按钮要显示一张标准的开根号图片,这用到了ImageButton。

    3.关键代码

    App同用户交互的过程中,时常要向用户反馈一些信息,例如:点错了按钮、输入了非法字符等等,诸如此类。对于这些一句话的提示,Android设计了Toast控件,用于展示短暂的提示文字。Toast的用法很简单,只需以下一行代码即可弹出提示小窗:

    Toast.makeText(MainActivity.this, "提示文字", Toast.LENGTH_SHORT).show();
    
    • 1

    上面代码用到了两个方法,分别是makeText和show,其中show方法用来展示提示窗,而makeText方法用来构建提示文字的模板。makeText的第一个参数为当前页面的实例,倘若当前页面名为MainActivity的话,这里就填MainActivity.this,当然如果不引发歧义的话,直接填this也可以;第二个参数为准备显示的提示文本;第三个参数规定了提示窗的驻留时长,为Toast.LENGTH_SHORT表示停留2秒后消失,为Toast.LENGTH_LONG表示停留3.5秒后消失。

    对于计算器来说,有好几种情况需要提示用户,比如“被除数不能为零”、“开根号的数值不能小于零”、“不能对零求倒数”等等,这时就能通过Toast控件弹窗提醒用户。Toast弹窗的展示效果如图3-37所示,此时App发现了被除数为零的情况。
    在这里插入图片描述
    对于简单计算来说,每次运算至少需要两个操作数,比如加减乘除四则运算就要求有两个操作数,求倒数、求平方、求开方只要求一个操作数;并且每次运算过程有且仅有一个运算符(等号不计在内),故而计算器App得事先声明下列几个字符串变量:

    private String operator = ""; // 运算符
    private String firstNum = ""; // 第一个操作数
    private String secondNum = ""; // 第二个操作数
    private String result = ""; // 当前的计算结果
    
    • 1
    • 2
    • 3
    • 4

    用户在计算器界面每输入一个按键,App都要进行下列两项操作:

    1.输入按键的合法性校验

    在开展计算之前,务必检查用户的按键是否合法,因为非法按键将导致不能正常运算。非法的按键输入包括但不限于下列情况:
    (1)被除数不能为零。
    (2)开根号的数值不能小于零。
    (3)不能对零求倒数。
    (4)一个数字不能有两个小数点。
    (5)如果没输入运算符,就不能点击等号按钮。
    (6)如果没输入操作数,也不能点击等号按钮。
    比如点击等号按钮之时,App的逻辑校验代码示例如下:

    if(v.getId()==R.id.btn_equal){ // 点击了等号按钮                                
         if(operator.equals("")){ // 无运算符                                    
             Toast.makeText(this,"请输入运算符",Toast.LENGTH_SHORT).show();        
             return false;                                                   
         }                                                                   
         if(firstNum.equals("")||secondNum.equals("")){ // 无操作数              
             Toast.makeText(this,"请输入数字",Toast.LENGTH_SHORT).show();         
             return false;                                                   
         }                                                                   
         if(operator.equals("÷")&&Double.parseDouble(secondNum)==0){ // 除数为零 
             Toast.makeText(this,"除数不能为零",Toast.LENGTH_SHORT).show();        
             return false;                                                   
         }                                                                   
     }                                                                       
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.执行运算并显示计算结果

    合法性校验通过,方能继续接下来的业务逻辑,倘若用户本次未输入与计算有关的按钮(例如等号、求倒数、求平方、求开方),则计算器只需拼接操作数或者运算符;倘若用户本次输入了与计算有关的按钮(例如等号、求倒数、求平方、求开方),则计算器立即执行运算操作并显示计算结果。以加减乘除四则运算为例,它们的计算代码例子如下所示:

    // 加减乘除四则运算,返回计算结果                                                           
    private double calculateFour() {                                             
        double calculate_result = 0;                                             
        if (operator.equals("+")) { // 当前是相加运算                                   
            calculate_result = Double.parseDouble(firstNum) +                    
                    Double.parseDouble(secondNum);                               
        } else if (operator.equals("-")) { // 当前是相减运算                            
            calculate_result = Double.parseDouble(firstNum) -                    
                    Double.parseDouble(secondNum);                               
        } else if (operator.equals("×")) { // 当前是相乘运算                            
            calculate_result = Double.parseDouble(firstNum) *                    
                    Double.parseDouble(secondNum);                               
        } else if (operator.equals("÷")) { // 当前是相除运算                            
            calculate_result = Double.parseDouble(firstNum) /                    
                    Double.parseDouble(secondNum);                               
        }                                                                        
        Log.d(TAG, "calculate_result=" + calculate_result); // 把运算结果打印到日志中       
        return calculate_result;                                                 
    }                                                                            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    完成合法性校验与运算处理之后,计算器App的编码基本结束了。运行计算器App,执行各种运算的界面效果如图3-38和图3-39所示。其中图3-38为执行乘法运算8×9=?的计算器界面,图3-39为先对8做开方再给开方结果加上60的计算器界面。

    简单计算器 - 详细操作步骤

    所需文件
    阿里云盘:sqrt.png https://www.aliyundrive.com/s/UUsRSZYALM4

    1.创建项目 CalcActivity
    打开android studio,选择【project】-【new project】
    在这里插入图片描述
    选择【phone and tablet】-【empty activity】-单击按钮【next】
    在这里插入图片描述
    设置name为 CalcActivity ,选择语言为 Java ,单击按钮【finish】
    在这里插入图片描述
    2.项目中新建一个CalcActivity活动页面
    选择【app】-【java】-【com.example.calcactivity】- 右击鼠标 - 选择【new】-【activity】-【empty activity】
    在这里插入图片描述
    在New Android Activity窗口中,输入 CalcActivity,单击按钮【Finish】
    在这里插入图片描述
    3.编写简易计算器的界面代码

    在【app】-【res】-【drawable】中插入一张透明背景的根号图片;并在【values】下创建一个dimens.xml文件。
    在这里插入图片描述
    dimens.xml文件主要设置计算器按钮的高度和显示在按钮上字体的大小、内容如下:

    
    
    
        30sp
        75dp
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    编写【values】文件下的strings.xml文件、内容如下:
    在这里插入图片描述

    
        CalcActivity
        简单计算器
        CE
        ÷
        ×
        C
        7
        8
        9
        
        4
        5
        6
        
        1
        2
        3
        1/x
        0
        .
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    编写【layout】文件下的activity_calc.xml文件、这里使用线性布局、内容如下:
    在这里插入图片描述

    
    
    
        
    
            
    
                
    
                
    
                
    
                    

    现在的运行效果截图,点击按钮无反应,无计算功能(后台响应)
    在这里插入图片描述
    在这里插入图片描述

    这里就相当于设计好了网页中的静态页面,后台响应还需要继续编写,才能实现计算功能。

    4.编写简易计算器后台计算功能
    编写【java】-【com.example.calcactivity】中的 CalcActivity
    在这里插入图片描述

    原始代码样式:
    在这里插入图片描述

    最后,CalcActivity.java源代码

    package com.example.calcactivity;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    
    public class CalcActivity extends AppCompatActivity implements View.OnClickListener {
    
        private TextView tv_result;
        // 第一个操作数
        private String firstNum = "";
        // 运算符
        private String operator = "";
        // 第二个操作数
        private String secondNum = "";
        // 当前的计算结果
        private String result = "";
        // 显示的文本内容
        private String showText = "";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_calc);
            // 从布局文件中获取名叫tv_result的文本视图
            tv_result = findViewById(R.id.tv_result); // 设置为全局变量
            // 下面给每个按钮控件都注册了点击监听器
            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); // 数字7
            findViewById(R.id.btn_eight).setOnClickListener(this); // 数字8
            findViewById(R.id.btn_nine).setOnClickListener(this); // 数字9
            findViewById(R.id.btn_plus).setOnClickListener(this); // “加法”按钮
            findViewById(R.id.btn_four).setOnClickListener(this); // 数字4
            findViewById(R.id.btn_five).setOnClickListener(this); // 数字5
            findViewById(R.id.btn_six).setOnClickListener(this); // 数字6
            findViewById(R.id.btn_minus).setOnClickListener(this); // “减法”按钮
            findViewById(R.id.btn_one).setOnClickListener(this); // 数字1
            findViewById(R.id.btn_two).setOnClickListener(this); // 数字2
            findViewById(R.id.btn_three).setOnClickListener(this); // 数字3
            findViewById(R.id.btn_reciprocal).setOnClickListener(this); // 求倒数按钮
            findViewById(R.id.btn_zero).setOnClickListener(this); // 数字0
            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) {
            String inputText;
            // 如果是开根号按钮
            if (v.getId() == R.id.ib_sqrt) {
                inputText = "√";
            } else {
                // 除了开根号之外的其他按钮
                inputText = ((TextView) v).getText().toString();
            }
            switch (v.getId()) {
                // 点击了清除按钮
                case R.id.btn_clear:
                    clear();
                    break;
                // 点击了取消按钮
                case R.id.btn_cancel:
                    break;
                // 点击了加、减、乘、除按钮
                case R.id.btn_plus:
                case R.id.btn_minus:
                case R.id.btn_multiply:
                case R.id.btn_divide:
                    operator = inputText; // 运算符
                    refreshText(showText + operator);
                    break;
                // 点击了等号按钮
                case R.id.btn_equal:
                    // 加减乘除四则运算
                    double calculate_result = calculateFour();
                    refreshOperate(String.valueOf(calculate_result));
                    refreshText(showText + "=" + result);
                    break;
                // 点击了开根号按钮
                case R.id.ib_sqrt:
                    double sqrt_result = Math.sqrt(Double.parseDouble(firstNum));
                    refreshOperate(String.valueOf(sqrt_result));
                    refreshText(showText + "√=" + result);
                    break;
                // 点击了求倒数按钮
                case R.id.btn_reciprocal:
                    double reciprocal_result = 1.0 / Double.parseDouble(firstNum);
                    refreshOperate(String.valueOf(reciprocal_result));
                    refreshText(showText + "/=" + result);
                    break;
                // 点击了其他按钮,包括数字和小数点
                default:
                    // 上次的运算结果已经出来了
                    if (result.length() > 0 && operator.equals("")) {
                        clear();
                    }
    
                    // 无运算符,则继续拼接第一个操作数
                    if (operator.equals("")) {
                        firstNum = firstNum + inputText;
                    } else {
                        // 有运算符,则继续拼接第二个操作数
                        secondNum = secondNum + inputText;
                    }
                    // 整数不需要前面的0
                    if (showText.equals("0") && !inputText.equals(".")) {
                        refreshText(inputText);
                    } else {
                        refreshText(showText + inputText);
                    }
                    break;
            }
    
        }
    
        // 加减乘除四则运算,返回计算结果
        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() {
            refreshOperate("");
            refreshText("");
        }
    
        // 刷新运算结果
        private void refreshOperate(String new_result) {
            result = new_result;
            firstNum = result;
            secondNum = "";
            operator = "";
        }
    
        // 刷新文本显示
        private void refreshText(String text) {
            showText = text;
            tv_result.setText(showText);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155

    总结

    本次主要介绍了App开发中常见简单控件的用法,包括:在文本视图上显示文本(设置文本的内容、大小和颜色)、修改视图的基本属性(设置视图的宽高、间距和对齐方式)、运用各种布局排列控件(线性布局、相对布局、网格布局、滚动视图)、处理按钮的触控事件(按钮控件的点击、长按、禁用与恢复)、在图像控件上显示图片(图像视图、图像按钮、同时展示文本与图像)。最后设计了一个实战项目“简单计算器”,在该项目的App编码中用到了前面介绍的大部分控件和布局,从而加深了对所学知识的理解。

    通过对本次的学习,读者应该能掌握以下4种开发技能:
    (1)学会在文本控件上正确展示文字。
    (2)学会在图像控件上正确展示图片。
    (3)学会正确处理按钮的点
    (4)学会在常见布局上排列组合多个控件。

  • 相关阅读:
    SlicePlane的Heading角度与Math.atan2(y,x)的对应转换关系
    ClickHouse的介绍(基本sql操作,以及数据库引擎、表引擎、分片、副本、explain、优化、物化视图等)
    SpringBoot: 启动
    【C++数据结构】线性表的本质和概念
    惠普笔记本重装系统后没有声音如何解决
    linux系统安全与应用【下】
    java-php-python-基于SSM智能社区管理系统计算机毕业设计
    MySQL之数据库理论
    6.3、Flink数据写入到MySQL
    算法设计与分析-0/1背包问题
  • 原文地址:https://blog.csdn.net/m0_62617719/article/details/127529255