Android 简单的计算器实现

1,425 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

文章目录

效果图

在这里插入图片描述

计算器设计思路

计算器的输入分为以下几种状态

  • 初始状态(什么都没输入之前)
  • 输入第一个数字
  • 点击了运算符
  • 输入第二个数字
  • 点击了等号

计算器的输入内容分为

  • 输入了数字
  • 输入了“.”
  • 输入了运算符
  • 输入了“=”

计算器的设计思路就是根据输入内容(数字、点、运算符、等号)分别处理计算器的不同状态就可以了

比如,现在输入的是数字,要处理的就是
1、初始状态输入数字的情况
2、输入了第一个数字再输入数字的情况
3、点击了运算符输入数字的情况
4、输入了第二个数字再输入数字的情况
5、点击了等号输入数字的情况

代码实现

xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="right" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right">

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="doClick"
            android:text="算式计算" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="doClick"
            android:text="AC" />
    </LinearLayout>

    <TableLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:stretchColumns="0,1,2,3">

        <TableRow android:layout_weight="1">

            <Button
                android:id="@+id/bt1"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="7" />

            <Button
                android:id="@+id/bt2"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="8" />

            <Button
                android:id="@+id/bt3"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="9" />

            <Button
                android:id="@+id/bt4"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="/" />
        </TableRow>

        <TableRow android:layout_weight="1">

            <Button
                android:id="@+id/bt5"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="4" />

            <Button
                android:id="@+id/bt6"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="5" />

            <Button
                android:id="@+id/bt7"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="6" />

            <Button
                android:id="@+id/bt8"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="*" />
        </TableRow>

        <TableRow android:layout_weight="1">

            <Button
                android:id="@+id/bt9"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="1" />

            <Button
                android:id="@+id/bt10"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="2" />

            <Button
                android:id="@+id/bt11"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="3" />

            <Button
                android:id="@+id/bt12"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="-" />
        </TableRow>

        <TableRow android:layout_weight="1">

            <Button
                android:id="@+id/bt13"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="." />

            <Button
                android:id="@+id/bt14"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="0" />

            <Button
                android:id="@+id/bt15"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="=" />

            <Button
                android:id="@+id/bt16"
                android:layout_height="match_parent"
                android:onClick="doClick"
                android:text="+" />
        </TableRow>
    </TableLayout>

</LinearLayout>

java

public class MainActivity extends AppCompatActivity {

    private EditText editText;
    /*
     *计算器使用状态
     * 0 初始状态
     * 1 输入第一个数字
     * 2 点击了运算符
     * 3 输入第二个数字
     * 4 点击了等号
     * */
    private int status;
    private double d1;//第一个数字
    private double d2;//第二个数字
    private String op;//运算符

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

        editText = findViewById(R.id.editText);
        editText.setText("0");
    }

    public void doClick(View v) {
        switch (v.getId()) {
            case R.id.button1:
                f1();
                break;
            case R.id.button2:
                reset();
                break;
            default:
                f2(v);
                break;
        }
    }

    private void reset() {
        status = 0;
        d1 = 0;
        d2 = 0;
        op = null;
        editText.setText("0");
    }

    private void f1() {

    }

    private void f2(View view) {
        Button button = (Button) view;
        String s = button.getText().toString();
        /*
         * 不同文本处理方式不同
         * 数字
         * 运算符
         * /
         * =
         */
        if (s.matches("\\d")) {
            shuzi(s);
        } else if (s.matches("[+\\-*/]")) {
            yunsuanfu(s);
        } else if (s.equals(".")) {
            dian();
        } else if (s.equals("=")) {
            denghao();
        }
    }

    private void denghao() {
        switch (status) {
            case 0:
                break;
            case 1:
                //输入第一个数字的时候点“=”
                status = 4;
                break;
            case 2:
                //输入运算符时,点击“=”
                //微软默认计算器输入如下“5+=”结果为10
                d2 = d1;
                double d = jisuan(d1, op, d2);
                editText.setText(String.valueOf(d));
                status = 4;
                break;
            case 3:
                d = jisuan(d1, op, d2);
                editText.setText(String.valueOf(d));
                status = 4;
                break;
            case 4:
                //点完“=”再点“=”
                //微软计算器输入“1+2=”,结果为“3”
                //此时再点“=”,相当于在此结果上再加“2”
                d1 = Double.parseDouble(editText.getText().toString());
                jisuan(d1, op, d2);
                break;
        }
    }

    private void dian() {
        //不同状态下点“.”字符
        switch (status) {
            case 0:
                //初始状态下点“.”,会直接显示“0.”,此时的状态变成输入第一个数字
                editText.setText("0.");
                status = 1;
                break;
            case 1:
                //输入第一个数字时,再点“.”,需要判断是否已经含有“.”
                String s = editText.getText().toString();
                if (!s.contains(".")) {
                    editText.append(".");
                }
                break;
            case 2:
                d2 = 0;
                editText.setText("0.");
                status = 3;
                break;
            case 3:
                //因为之前已经定义“s”,不用重复定义,可以覆盖后边所有“s”
                s = editText.getText().toString();
                if (!s.contains(".")) {
                    editText.append(".");
                }
                break;
            case 4:
                //点完等号再点“.”,相当于一次新的运算
                reset();
                editText.setText("0.");
                status = 1;
                break;
        }
    }

    private void yunsuanfu(String s) {
        //不同状态下点击运算符
        switch (status) {
            //初始状态下点击运算符
            case 0:
                d1 = 0;
                status = 2;
                op = s;
                break;
            //正在输入第一个数
            case 1:
                op = s;
                status = 2;
                break;
            //点完运算符,再点运算符
            case 2:
                op = s;
                break;
            //输入第二个数的时候点击运算符
            case 3:
                //求出上一次的结果作为新的计算的第一个数字
                d1 = jisuan(d1, op, d2);
                editText.setText(String.valueOf(d1));
                op = s;
                status = 2;
                break;
            case 4:
                d1 = Double.parseDouble(editText.getText().toString());
                op = s;
                status = 2;
                break;
        }
    }

    private double jisuan(double a, String op, double b) {
        double r = 0;

        switch (op.charAt(0)) {
            case '+':
                r = a + b;
                break;
            case '-':
                r = a - b;
                break;
            case '*':
                r = a * b;
                break;
            case '/':
                r = a / b;
                break;
        }

        return r;
    }

    private void shuzi(String s) {
        //在不同状态下点击数字按钮
        switch (status) {
            //初始状态下,点击数字按钮直接显示
            case 0:
                editText.setText(s);
                d1 = Double.parseDouble(s);
                status = 1;
                break;
            case 1:
                editText.append(s);
                d1 = Double.parseDouble(editText.getText().toString());
                break;
            //点击符号后输入第二个数字
            case 2:
                editText.setText(s);
                d2 = Double.parseDouble(s);
                status = 3;
                break;
            //输入第二个数字的状态
            case 3:
                editText.append(s);
                d2 = Double.parseDouble(editText.getText().toString());
                break;
            //点完等号,再点数字。相当于一次新的计算
            case 4:
                editText.setText(s);
                d1 = Double.parseDouble(s);
                status = 1;
                break;
        }
    }
}

注意:f1() 方法为算式计算器跳转方法。算式计算器的实现为下一篇文章

源码下载