制作一个简易的计算器app

github项目地址:https://github.com/13008451162/AndroidMoblieCalculator

1、Ui开发

笔者的Ui制作的制作的比较麻烦仅供参考,在这里使用了多个LinearLayout对屏幕进行了划分。不建议大家这样做最好使用GridLayout会更加快捷简单

笔者大致划分是这样的:

image-20230723165001763

使用了四个大框,在第四个大框里面有多个小框

image-20230723165045992
最终界面如下:
在这里插入图片描述

然后在每一个小框写计算机的按键。

代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/TwoArrows_Shrink"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginTop="15dp"
            android:layout_marginLeft="10dp"
            android:src="@drawable/two_arrows_shrink"/>

        <ImageView
            android:id="@+id/FourSquares"
            android:layout_width="30dp"
            android:layout_height="30dp"
           android:layout_marginLeft="220dp"
            android:layout_marginTop="15dp"
            android:src="@drawable/four_squares"/>

        <ImageView
            android:id="@+id/ThreePoints"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginLeft="15dp"
            android:clickable="true"
            android:layout_marginTop="15dp"
            android:src="@drawable/three_points"/>
    </LinearLayout>

    <EditText
        android:id="@+id/Scanf_EditText"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="3"
        android:background="@null"
        android:gravity="bottom|right"
        android:text=""
        android:lines="1"
        android:inputType="textVisiblePassword"
        android:textSize="40dp"
        android:paddingRight="16dp"
        android:textColor="@android:color/black"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/Printf_text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center|right"
        android:text=""
        android:textSize="25dp"
        android:layout_margin="8dp"
        android:paddingRight="13dp"
        android:textColor="@android:color/black"
        android:textStyle="bold" />

    <LinearLayout
        android:id="@+id/keyboard"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="5"
        android:orientation="vertical"
        android:layout_margin="10dp">

        <!--  C % <- /      -->
        <LinearLayout
            android:id="@+id/One"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            >

            <!--            C-->
            <FrameLayout
                android:id="@+id/leftCFrmae"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
              >

                <ImageButton
                    android:id="@+id/leftC"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_grey_round"
                    android:layout_marginStart="20dp"
                    />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="("
                    android:textSize="25sp"
                    android:textColor="@android:color/black"
                    android:layout_gravity="center"
                    android:layout_marginLeft="10dp"
                    android:padding="8dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4"/>
            </FrameLayout>

            <FrameLayout
                android:id="@+id/RightCFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="20dp">

                <ImageButton
                    android:id="@+id/RightC"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_grey_round"/>

                <TextView
                    android:layout_width="19dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:paddingLeft="10dp"

                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4"
                    android:text=")"
                    android:textColor="@android:color/black"
                    android:textSize="25sp" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/DeleteOneFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/DeleteOne"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_grey_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="DEL"
                    android:textColor="@android:color/black"
                    android:textSize="25sp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4"/>
            </FrameLayout>

            <FrameLayout
                android:id="@+id/DivisionFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/Division"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_grey_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text=""
                    android:textColor="@android:color/black"
                    android:textSize="25sp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4"/>
            </FrameLayout>

        </LinearLayout>

        <!-- 7 8 9 x       -->
        <LinearLayout
            android:id="@+id/Two"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingTop="15dp"
            >

            <FrameLayout
                android:id="@+id/SevenNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/SevenNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="7"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />

            </FrameLayout>

            <FrameLayout
                android:id="@+id/EightNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/EightNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="8"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />

            </FrameLayout>

            <FrameLayout
                android:id="@+id/NineNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/NineNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="9"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />

            </FrameLayout>

            <FrameLayout
                android:id="@+id/MultiplyFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageView
                    android:id="@+id/Multiply"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_grey_round"
                    android:layout_marginStart="20dp"
                    android:scaleType="centerInside"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="✖️"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

        </LinearLayout>

        <!-- 4 5 6 -      -->
        <LinearLayout
            android:id="@+id/Three"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingTop="15dp"
            >
            <FrameLayout
                android:id="@+id/FourNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/FourNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="4"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/FiveNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/FiveNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="5"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/SixNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/SixNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="6"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/BubFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/Sub"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_grey_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text=""
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>


        </LinearLayout>

        <!-- 1 2 3 +      -->
        <LinearLayout
            android:id="@+id/Four"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingTop="15dp"
            >
            <FrameLayout
                android:id="@+id/OneNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/OneNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="1"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/TwoNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/TwoNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="2"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/ThreeNumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/ThreeNum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="3"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/AddFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/add"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_grey_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text=""
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>


        </LinearLayout>

        <!-- 00 0 . =      -->
        <LinearLayout
            android:id="@+id/Five"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingTop="15dp"
            >
            <FrameLayout
                android:id="@+id/CFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/C"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="C"
                    android:textSize="25sp"
                    android:textColor="@android:color/black"
                    android:layout_gravity="center"
                    android:layout_marginLeft="10dp"
                    android:padding="8dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4"/>
            </FrameLayout>

            <FrameLayout
                android:id="@+id/ONumFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/O"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:padding="8dp"
                    android:text="0"
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/PointFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/Point"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_white_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:paddingBottom="10dp"
                    android:text="."
                    android:textColor="@android:color/black"
                    android:textSize="28dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

            <FrameLayout
                android:id="@+id/equalFrame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageButton
                    android:id="@+id/equal"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/button_orange_round"
                    android:layout_marginStart="20dp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="11dp"
                    android:paddingBottom="15dp"
                    android:text=""
                    android:textColor="@android:color/white"
                    android:textSize="45dp"
                    android:shadowColor="#80000000"
                    android:shadowDx="2"
                    android:shadowDy="2"
                    android:shadowRadius="4" />
            </FrameLayout>

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

我们简单分解一下代码中的重点

1.1 给文本制作阴影并加粗

<TextView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="("
          android:textSize="25sp"
          android:textColor="@android:color/black"
          android:layout_gravity="center"
          android:layout_marginLeft="10dp"
          android:padding="8dp"
          android:shadowColor="#80000000"
          android:shadowDx="2"
          android:shadowDy="2"
          android:shadowRadius="4"
          android:textStyle="bold/>
  1. android:shadowColor="#80000000":表示为该视图的文本添加阴影效果,阴影颜色为半透明黑色(#80000000)。
  2. android:shadowDx="2":表示阴影在水平方向上的偏移量为2个像素。
  3. android:shadowDy="2":表示阴影在垂直方向上的偏移量为2个像素。
  4. android:shadowRadius="4":表示阴影的模糊半径为4个像素。
  5. android:textStyle="bold":是对TextView(文本视图)的一个属性设置,用于指定文本的字体样式为粗体(加粗)。

2.2 制作圆形按钮

在drawable目录下新建xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/orange" />
    <size android:height="60dp" android:width="60dp"/>
</shape>

android:shape指定图形,常用参数有:

  1. "rectangle": 表示创建一个矩形的形状。
  2. "oval": 表示创建一个椭圆的形状,也就是圆形。
  3. "line": 表示创建一条线段的形状。
  4. "ring": 表示创建一个圆环的形状。
  5. "line": 表示创建一条线段的形状。

solid:用于填充颜色

**size **:用于指定大小,因为是圆形我们这里长宽都要设置为相同

效果如下:

image-20230723170250310

2.3 制作点击变色的按钮

笔者在这里,没有使用点击变色而是使用了动画,后面介绍动画。这里介绍一下怎么点击变色。

首先还是在drawable目录下新建一个xml文件

<?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="oval">
        <solid android:color="@color/Greywhite" />
        <size android:height="60dp" android:width="60dp"/>
    </shape>
</item>
<!-- 定义普通状态的样式 -->
<item>
    <shape android:shape="oval">
        <solid android:color="@color/Greywhite4" />
        <size android:height="60dp" android:width="60dp"/>
    </shape>
</item>
</selector>

设置一个selector,如何设置两个item选项,设置为android:state_pressed="true"的选项在点击后就会产生对应的变化。

2、点击事件与界面处理

1、禁用输入法修改EditText文本内容

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

        activityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(activityMainBinding.getRoot());

        //禁用输入法修改EditText文本内容
        activityMainBinding.ScanfEditText.setInputType(InputType.TYPE_NULL);

        //传入各个按键
        //功能键
        activityMainBinding.C.setOnClickListener(this);
        activityMainBinding.DeleteOne.setOnClickListener(this);

        //加减乘除,括号,等于
        activityMainBinding.add.setOnClickListener(this);
        activityMainBinding.Sub.setOnClickListener(this);
        activityMainBinding.Multiply.setOnClickListener(this);
        activityMainBinding.Division.setOnClickListener(this);
        activityMainBinding.leftC.setOnClickListener(this);
        activityMainBinding.RightC.setOnClickListener(this);
        activityMainBinding.equal.setOnClickListener(this);

        //数字,小数点
        activityMainBinding.O.setOnClickListener(this);
        activityMainBinding.OneNum.setOnClickListener(this);
        activityMainBinding.TwoNum.setOnClickListener(this);
        activityMainBinding.ThreeNum.setOnClickListener(this);
        activityMainBinding.FourNum.setOnClickListener(this);
        activityMainBinding.FiveNum.setOnClickListener(this);
        activityMainBinding.SixNum.setOnClickListener(this);
        activityMainBinding.SevenNum.setOnClickListener(this);
        activityMainBinding.EightNum.setOnClickListener(this);
        activityMainBinding.NineNum.setOnClickListener(this);
        activityMainBinding.Point.setOnClickListener(this);


        activityMainBinding.TwoArrowsShrink.setOnClickListener(this);

        //长按触发菜单
        registerForContextMenu(activityMainBinding.ThreePoints);


    }
        activityMainBinding.ScanfEditText.setInputType(InputType.TYPE_NULL);

通过设置 InputType.TYPE_NULLEditText 将不再响应输入法的输入,用户无法通过软键盘输入文本内容。这样做的目的通常是为了限制用户只能通过其他途径(比如扫码、点击按钮等)来输入文本内容,而不能直接通过键盘输入。如何我们为每个按钮注册监听事件

2、按键缩放动画和实现震动效果

    private void animation(View view) {
        // 加载缩放动画资源
        final AnimatorSet scaleAnimation = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.scale_animation);

        //实现震动效果
        /**
         *         Vibrator vibrator=(Vibrator)getSystemService(Service.VIBRATOR_SERVICE);
         *         vibrator.vibrate(new long[]{0,100}, -1);
         * 从Android API level 26开始,Vibrator类的vibrate()方法被弃用,推荐使用VibrationEffect来实现震动效果。VibrationEffect类提供了更灵活和可控的震动方式。
         */
        // 获取Vibrator实例
        Vibrator vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);

        // 判断Android版本是否大于等于API 26
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 创建VibrationEffect对象,指定震动模式和震动时长100ms
            VibrationEffect vibrationEffect = VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE);
            // 开始震动
            vibrator.vibrate(vibrationEffect);
        } else {
            // Android版本低于API 26,使用老版本的vibrate方法
            //震动时间为100ms
            vibrator.vibrate(100);
        }

        // 开始执行缩放动画
        scaleAnimation.setTarget(view);
        scaleAnimation.start();

        scaleAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {

                // 在缩放动画结束时,创建还原动画并执行还原动画
                ObjectAnimator restoreAnimationX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f);
                ObjectAnimator restoreAnimationY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f);
                AnimatorSet restoreAnimation = new AnimatorSet();
                restoreAnimation.playTogether(restoreAnimationX, restoreAnimationY);
                restoreAnimation.start();
            }
        });
    }

首先加载缩放动画资源。

final AnimatorSet scaleAnimation = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.scale_animation);

scale_animationanimator下设置的动画属性

具体设置如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="scaleX"
        android:valueFrom="1.0"
        android:valueTo="0.9"
        android:duration="100"
        android:repeatCount="0"
        android:repeatMode="restart"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator" />
    <objectAnimator
        android:propertyName="scaleY"
        android:valueFrom="1.0"
        android:valueTo="0.9"
        android:duration="100"
        android:repeatCount="0"
        android:repeatMode="restart"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator" />
</set>
  1. android:propertyName: 定义要动画化的属性的名称。在这里,scaleXscaleY 分别表示水平和垂直方向的缩放。
  2. android:valueFrom: 定义动画的起始值。这里起始值为 1.0,表示不缩放。
  3. android:valueTo: 定义动画的结束值。这里结束值为 0.9,表示缩放到原始大小的 0.9 倍。
  4. android:duration: 定义动画的持续时间,以毫秒为单位。这里持续时间为 100 毫秒,即缩放动画的过程为 0.1 秒。
  5. android:repeatCount: 定义动画重复的次数。这里设置为 0,表示动画不重复。
  6. android:repeatMode: 定义动画重复的模式。这里设置为 restart,表示每次重复动画都从头开始。
  7. android:interpolator: 定义动画的插值器,用于控制动画的变化速率。这里使用了 Android 系统自带的 accelerate_decelerate_interpolator 插值器,表示动画先加速后减速。

这个 XML 文件定义了两个属性动画,分别是在水平方向和垂直方向上的缩放动画效果。在 Android 应用中,你可以通过加载这个 XML 文件来应用这个缩放动画,让指定的视图(如 ViewImageView)在缩放动画的作用下,由原始大小缩放到 0.9 倍的大小。

制作动画时,创建了一个 scaleAnimation 缩放动画,然后给该动画添加了一个监听器 AnimatorListenerAdapter。在监听器的 onAnimationEnd() 方法中,当缩放动画结束时,会执行还原动画。

大致逻辑:

  1. 创建缩放动画 scaleAnimation 并设置属性动画的相关参数。
  2. scaleAnimation 添加一个监听器,在缩放动画结束时执行还原动画。
  3. 创建两个 ObjectAnimator 分别对 viewscaleXscaleY 属性进行动画处理,将 view 的缩放比例恢复为原始大小(1.0f)。
  4. 将还原动画 restoreAnimation 中的两个动画一起播放。

3、实现显示框字体大小变化的动画

当我们计算完结果后,我们让计算的结果变大,计算的算式变小

private void DisplayFrameAnimation(View Little_big, View Big_little) {        
    // 加载动画资源,从25变到40
    AnimatorSet Little_Big = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_25_40);
    // 设置目标视图
    Little_Big.setTarget(Little_big);
    // 启动动画
    Little_Big.start();

    // 加载动画资源,从40变到25
    AnimatorSet Big_Little = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_40_25);
    // 设置目标视图
    Big_Little.setTarget(Big_little);
    // 启动动画
    Big_Little.start();
}

AnimatorInflater: 这是一个用于加载属性动画的类。它提供了一个方法 loadAnimator(),可以通过指定资源ID加载属性动画。

  1. this: 这里的 this 指的是当前的上下文,即所在的 Activity
  2. R.animator.text_size_40_25: 这是指定的属性动画资源的资源ID。在这里,text_size_40_25 是一个位于 res/animator 目录下的 XML 文件,它定义了一组属性动画。

同样这样的操作需要动画文件,我们在这里介绍一下字体大小由25变化到40的

<?xml version="1.0" encoding="utf-8"?>
<!-- text_size_change.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="textSize"
        android:valueType="floatType"
        android:valueFrom="25"
        android:valueTo="40"
        android:duration="500"
        />
</set>
  1. <set>:这是属性动画的根元素,用于定义属性动画集合。在这里,我们只有一个动画,所以只有一个 <objectAnimator> 子元素。
  2. <objectAnimator>:这是一个对象动画元素,用于定义属性动画。它有以下属性:
    • android:propertyName="textSize":这是要动画化的属性名称,即视图的文本大小属性 textSize
    • android:valueType="floatType":这是动画值的类型,这里是浮点数类型,用于表示文本大小。
    • android:valueFrom="25":这是动画的起始值,即文本大小的初始值为 25。
    • android:valueTo="40":这是动画的结束值,即文本大小的目标值为 40。
    • android:duration="500":这是动画的持续时间,即从起始值到结束值的过渡时间为 500 毫秒。

3、逻辑与算法

1.1 按钮点击结果的分析与处理

package com.example.computermoblie;

import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Service;
import android.os.Build;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.text.InputType;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.example.computermoblie.databinding.ActivityMainBinding;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    // 计算器储存总数据的上限
    public List<String> SumNumber = new ArrayList<>();

    //计算器存储的数字上限
    private StringBuilder Number = new StringBuilder();


    //当前输入框字体大小,初始状态为40dp
    private int SIzeOfText = 40;

    public ActivityMainBinding activityMainBinding;

    private boolean GetEqual = false;    //表示没有按下等号

    private boolean NegativeSymbol = false; //表示不是负数的符号

    public String ret; //运算结果

    private static final String Del = "Delete"; //表示删除键

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

        activityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(activityMainBinding.getRoot());

        //禁用输入法修改EditText文本内容
        activityMainBinding.ScanfEditText.setInputType(InputType.TYPE_NULL);

        //传入各个按键
        //功能键
        activityMainBinding.C.setOnClickListener(this);
        activityMainBinding.DeleteOne.setOnClickListener(this);

        //加减乘除,括号,等于
        activityMainBinding.add.setOnClickListener(this);
        activityMainBinding.Sub.setOnClickListener(this);
        activityMainBinding.Multiply.setOnClickListener(this);
        activityMainBinding.Division.setOnClickListener(this);
        activityMainBinding.leftC.setOnClickListener(this);
        activityMainBinding.RightC.setOnClickListener(this);
        activityMainBinding.equal.setOnClickListener(this);

        //数字,小数点
        activityMainBinding.O.setOnClickListener(this);
        activityMainBinding.OneNum.setOnClickListener(this);
        activityMainBinding.TwoNum.setOnClickListener(this);
        activityMainBinding.ThreeNum.setOnClickListener(this);
        activityMainBinding.FourNum.setOnClickListener(this);
        activityMainBinding.FiveNum.setOnClickListener(this);
        activityMainBinding.SixNum.setOnClickListener(this);
        activityMainBinding.SevenNum.setOnClickListener(this);
        activityMainBinding.EightNum.setOnClickListener(this);
        activityMainBinding.NineNum.setOnClickListener(this);
        activityMainBinding.Point.setOnClickListener(this);


        activityMainBinding.TwoArrowsShrink.setOnClickListener(this);

        //长按触发菜单
        registerForContextMenu(activityMainBinding.ThreePoints);


    }

    @Override
    public void onClick(View view) {
        final int Id = view.getId();
        // 调用按键动画
        animation(view);

        //退出
        if(Id == R.id.TwoArrows_Shrink){
            finish();
        }


        //功能按钮
        if (Id == R.id.C) {
            //清空显示
            activityMainBinding.ScanfEditText.setText("");
            ret = "";
            activityMainBinding.PrintfText.setText(ret);

            //清空储存的内容
            SumNumber.clear();
            Number.setLength(0);

            //还原字体大小
            SIzeOfText = 40;

        } else {
            if (Id == R.id.leftC) {

                if (!GetEqual) {
                    if (Number.length() > 0) {
                        char cat = Number.charAt(Number.length() - 1);
                        if (cat != '.' && !Character.isDigit(cat)) {
                            SumNumber.add("(");

                        } else {
                            //左括号前面没有符号只有数字默认为乘号
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }
                            Number.setLength(0);
                            SumNumber.add("×");
                            SumNumber.add("(");
                        }
                    } else if (!SumNumber.isEmpty()) {
                        //判断是不是存在两个相邻的操作
                        String str = SumNumber.get(SumNumber.size() - 1);
                        if (!str.equals("+") && !str.equals("-") && !str.equals("×") && !str.equals("÷") && !str.equals("(")) {
                            SumNumber.add("×");
                            SumNumber.add("(");
                        } else {
                            SumNumber.add("(");
                        }
                    }

                    //开头就使用括号的情况
                    if (SumNumber.isEmpty()){
                        SumNumber.add("(");
                    }
                }
            }

            if (Id == R.id.RightC) {
                if (!GetEqual) {
                    if (Number.length() > 0) {
                        char cat = Number.charAt(Number.length() - 1);
                        if (cat != '.') {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }
                            Number.setLength(0);
                            SumNumber.add(")");

                            //使得按下后动态计算结果
                            DynamicCalculation();
                        }
                    } else if (!SumNumber.isEmpty()) {
                        //判断是不是存在两个相邻的操作
                        String str = SumNumber.get(SumNumber.size() - 1);
                        Log.d("DEL1", SumNumber.toString());
                        if (!str.equals("+") && !str.equals("-") && !str.equals("×") && !str.equals("÷") && !str.equals("(")) {
                            SumNumber.add(")");
                            //使得按下后动态计算结果
                            DynamicCalculation();
                        }
                    }
                }
            }

            if (Id == R.id.DeleteOne) {
                if (!GetEqual) {
                    if (Number.length() > 0) {
                        Number.deleteCharAt(Number.length() - 1);
                    } else if (SumNumber.size() > 0) {
                        try {
                            Number.setLength(0);
                            Number.append(SumNumber.remove(SumNumber.size() - 1));
                            Number.deleteCharAt(Number.length() - 1);
                        }catch (NumberFormatException e){
                            Log.d("Number", "出现空值");
                        }
                    }else {
                        ret = "";
                        activityMainBinding.PrintfText.setText(ret);
                    }

                    //删除所有数据后清除结果
                    if (SumNumber.isEmpty()){
                        ListComputing(Del);
                    }
                }else {
                    ListComputing(Del);
                }

                //使得按下后动态计算结果
                DynamicCalculation();
            }

            //加减乘除
            if (Id == R.id.add) {
                if (!GetEqual) {
                    if (Number.length() > 0) {
                        if (Number.charAt(Number.length() - 1) != '.') {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }

                            Number.setLength(0);
                            SumNumber.add("+");
                        }
                    } else if (!SumNumber.isEmpty()) {
                        //判断是不是存在两个相邻的操作
                        String str = SumNumber.get(SumNumber.size() - 1);
                        if (!str.equals("+") && !str.equals("-") && !str.equals("×") && !str.equals("÷") && !str.equals("(")) {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }

                            Log.d("String1", String.valueOf(Number));
                            Number.setLength(0);
                            SumNumber.add("+");
                        }
                    }
                } else {
                    ListComputing("+");
                }
            }

            if (Id == R.id.Sub) {
                if (!GetEqual) {
                    if (Number.length() > 0) {
                        if (Number.charAt(Number.length() - 1) != '.') {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }

                            Log.d("String1", String.valueOf(Number));
                            Number.setLength(0);
                            SumNumber.add("-");
                        }
                    } else if (!SumNumber.isEmpty()) {
                        //判断是不是存在两个相邻的操作
                        String str = SumNumber.get(SumNumber.size() - 1);
                        if (!str.equals("+") && !str.equals("-") && !str.equals("×") && !str.equals("÷") && !str.equals("(")) {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }

                            Log.d("String1", String.valueOf(Number));
                            Number.setLength(0);
                            SumNumber.add("-");
                        } else if (str.equals("×") || str.equals("÷")||str.equals("(")) {
                            Number.append("-");
                        }
                    }else {
                        Number.append("-");
                    }
                } else {
                    ListComputing("-");
                }
            }

            if (Id == R.id.Multiply) {
                if (!GetEqual) {
                    if (Number.length() > 0) {
                        if (Number.charAt(Number.length() - 1) != '.') {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }

                            Log.d("String1", String.valueOf(Number));
                            Number.setLength(0);
                            SumNumber.add("×");
                        }
                    } else if (!SumNumber.isEmpty()) {
                        //判断是不是存在两个相邻的操作
                        String str = SumNumber.get(SumNumber.size() - 1);
                        if (!str.equals("+") && !str.equals("-") && !str.equals("×") && !str.equals("÷") && !str.equals("(")) {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }

                            Log.d("String1", String.valueOf(Number));
                            Number.setLength(0);
                            SumNumber.add("×");
                        }
                    }
                } else {
                    ListComputing("×");
                }
            }

            if (Id == R.id.Division) {
                if (!GetEqual) {

                    if (Number.length() > 0) {
                        if (Number.charAt(Number.length() - 1) != '.') {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }

                            Log.d("String1", String.valueOf(Number));
                            Number.setLength(0);
                            SumNumber.add("÷");
                        }
                    } else if (!SumNumber.isEmpty()) {
                        //判断是不是存在两个相邻的操作
                        String str = SumNumber.get(SumNumber.size() - 1);
                        if (!str.equals("+") && !str.equals("-") && !str.equals("×") && !str.equals("÷") && !str.equals("(")) {
                            //将number的数据放入Sumnumber
                            if (!Number.equals("") && Number != null) {
                                //保存数据
                                try {
                                    SumNumber.add(String.valueOf(Number));
                                } catch (NumberFormatException e) {
                                    Log.d("Number", "出现空值");
                                }

                            }

                            Log.d("String1", String.valueOf(Number));
                            Number.setLength(0);
                            SumNumber.add("÷");
                        }
                    }
                } else {
                    ListComputing("÷");
                }
            }

            //数字
            if (Id == R.id.OneNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("1");

//                //使得按下数字后动态计算结果
                DynamicCalculation();
            }

            if (Id == R.id.TwoNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("2");

//                //使得按下数字后动态计算结果
                DynamicCalculation();
            }

            if (Id == R.id.ThreeNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("3");

//                //使得按下数字后动态计算结果
                DynamicCalculation();
            }

            if (Id == R.id.FourNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("4");

//                //使得按下数字后动态计算结果
                DynamicCalculation();
            }
            if (Id == R.id.FiveNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("5");

//                //使得按下数字后动态计算结果
                DynamicCalculation();
            }

            if (Id == R.id.SixNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("6");

//                //使得按下数字后动态计算结果
                DynamicCalculation();
            }

            if (Id == R.id.SevenNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("7");

//                //使得按下数字后动态计算结果
                DynamicCalculation();
            }

            if (Id == R.id.EightNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("8");

//                //使得按下数字后动态计算结果
                DynamicCalculation();
            }
            if (Id == R.id.NineNum) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("9");

                //使得按下数字后动态计算结果
                DynamicCalculation();
            }
            if (Id == R.id.O) {
                ClearDisplay();//清空显示
                if (!SumNumber.isEmpty()) {
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        SumNumber.add("×");
                    }
                }
                Number.append("0");

                //使得按下数字后动态计算结果
                DynamicCalculation();
            }


            if (Id == R.id.Point) {
                if (Number.length() > 0) {
                    int t = 0;
                    for (int i = 0; i < Number.length(); i++) {
                        if (Number.charAt(i) == '.') {
                            t++;
                        }
                    }
                    if (t < 1) {
                        Number.append(".");
                    }
                }
            }

            if (Id == R.id.equal) {
                if (Number.length() > 0) {
                    if (Number.charAt(Number.length() - 1) != '.') {
                        //将number的数据放入Sumnumber
                        if (!Number.equals("") && Number != null) {
                            //保存数据
                            try {
                                SumNumber.add(String.valueOf(Number));
                            } catch (NumberFormatException e) {
                                Log.d("Number", "出现空值");
                            }

                        }

                        Number.setLength(0);

                        //表示等号已经按下,用于清除文本框
                        GetEqual = true;

                        //计算结果
                        ReversePolish reversePolish = new ReversePolish(SumNumber);
                        ret = reversePolish.EvaluatePostfixExpressions();
                        //加载大小变化的动画
                        DisplayFrameAnimation(activityMainBinding.PrintfText, activityMainBinding.ScanfEditText);
                    }
                } else if (!SumNumber.isEmpty()) {
                    //判断是不是存在两个相邻的操作
                    String str = SumNumber.get(SumNumber.size() - 1);
                    if (str.equals(")")) {
                        //将number的数据放入Sumnumber
                        if (!Number.equals("") && Number != null) {
                            //保存数据
                            try {
                                SumNumber.add(String.valueOf(Number));
                            } catch (NumberFormatException e) {
                                Log.d("Number", "出现空值");
                            }

                        }

                        Number.setLength(0);

                        //表示等号已经按下,用于清除文本框
                        GetEqual = true;

                        //计算结果
                        ReversePolish reversePolish = new ReversePolish(SumNumber);
                        ret = reversePolish.EvaluatePostfixExpressions();

                        //加载大小变化的动画
                        DisplayFrameAnimation(activityMainBinding.PrintfText, activityMainBinding.ScanfEditText);
                    }
                }
            }

            //显示文本框内容
            if (Number != null) {
                StringBuilder builder = new StringBuilder();
                for (String str : SumNumber) {
                    builder.append(str);
                }
                builder.append(Number);
                activityMainBinding.ScanfEditText.setText(builder);
                activityMainBinding.PrintfText.setText(ret);
                MaxDisplayFrameAnimation(activityMainBinding.ScanfEditText);
            }

        }


    }

    //按键缩放动画和实现震动效果
    private void animation(View view) {
        // 加载缩放动画资源
        final AnimatorSet scaleAnimation = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.scale_animation);

        //实现震动效果
        /**
         *         Vibrator vibrator=(Vibrator)getSystemService(Service.VIBRATOR_SERVICE);
         *         vibrator.vibrate(new long[]{0,100}, -1);
         * 从Android API level 26开始,Vibrator类的vibrate()方法被弃用,推荐使用VibrationEffect来实现震动效果。VibrationEffect类提供了更灵活和可控的震动方式。
         */
        // 获取Vibrator实例
        Vibrator vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);

        // 判断Android版本是否大于等于API 26
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 创建VibrationEffect对象,指定震动模式和震动时长
            VibrationEffect vibrationEffect = VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE);
            // 开始震动
            vibrator.vibrate(vibrationEffect);
        } else {
            // Android版本低于API 26,使用老版本的vibrate方法
            vibrator.vibrate(100);
        }

        // 开始执行缩放动画
        scaleAnimation.setTarget(view);
        scaleAnimation.start();

        scaleAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {

                // 在缩放动画结束时,创建还原动画并执行还原动画
                ObjectAnimator restoreAnimationX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f);
                ObjectAnimator restoreAnimationY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f);
                AnimatorSet restoreAnimation = new AnimatorSet();
                restoreAnimation.playTogether(restoreAnimationX, restoreAnimationY);
                restoreAnimation.start();
            }
        });
    }


    // 显示框的动画效果
    private void DisplayFrameAnimation(View Little_big, View Big_little) {

        /**
         * SIzeOfText == 40 由上方40-25 下方25-40
         * SIzeOfText == 30 由上方30-25 下方25-30
         * SIzeOfText == 25 由上方不变 下方25-30
         */


        if (SIzeOfText == 40) {
            // 加载动画资源,从25变到40
            AnimatorSet Little_Big = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_25_40);
            // 设置目标视图
            Little_Big.setTarget(Little_big);
            // 启动动画
            Little_Big.start();

            // 加载动画资源,从40变到25
            AnimatorSet Big_Little = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_40_25);
            // 设置目标视图
            Big_Little.setTarget(Big_little);
            // 启动动画
            Big_Little.start();
        } else if (SIzeOfText == 30) {
            Log.d("SIzeOfText", String.valueOf(SIzeOfText));

            // 加载动画资源,从25变到30
            AnimatorSet Little_Big = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_25_30);
            // 设置目标视图
            Little_Big.setTarget(Little_big);
            // 启动动画
            Little_Big.start();

            // 加载动画资源,从30变到25
            AnimatorSet Big_Little = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_30_25);
            // 设置目标视图
            Big_Little.setTarget(Big_little);
            // 启动动画
            Big_Little.start();
        } else if (SIzeOfText == 25) {
            // 加载动画资源,从25变到30
            AnimatorSet Little_Big = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_25_30);
            // 设置目标视图
            Little_Big.setTarget(Little_big);
            // 启动动画
            Little_Big.start();
        }

    }

    //显示框的字符达到指定长度使得一行无法放下
    private void MaxDisplayFrameAnimation(View Big_littleView) {
        int MaxDigit = 0;
        for (String str : SumNumber) {
            MaxDigit += str.length();
        }

        MaxDigit += Number.length();

        Log.d("StrSize", "num:" + MaxDigit);
        if (MaxDigit == 10) {

            SIzeOfText = 30;    //字体变化为30

            // 加载动画资源,从40变到30
            AnimatorSet Big_Little = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_40_30);
            // 设置目标视图
            Big_Little.setTarget(Big_littleView);
            // 启动动画
            Big_Little.start();

        }
        if (MaxDigit > 10 && MaxDigit < 25) activityMainBinding.ScanfEditText.setTextSize(30);

        if (MaxDigit == 15) {

            SIzeOfText = 25;    //字体变化为25

            // 加载动画资源,从30变到25
            AnimatorSet Big_Little = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.text_size_30_25);
            // 设置目标视图
            Big_Little.setTarget(Big_littleView);

            // 启动动画
            Big_Little.start();


            activityMainBinding.ScanfEditText.setTextSize(25);
        }
        if (MaxDigit > 15) activityMainBinding.ScanfEditText.setTextSize(25);

    }


    //加载菜单
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        Log.d("Tag", "加载菜单");
        getMenuInflater().inflate(R.menu.function, menu);
        super.onCreateContextMenu(menu, v, menuInfo);
    }

    //注册菜单点击事件
    @Override
    public boolean onContextItemSelected(@NonNull MenuItem item) {
        Log.d("Tag", "点击事件");
        final int Id = item.getItemId();


        if (Id == R.id.Log) {
            //历史记录

        } else if (Id == R.id.SetUp) {
            //设置

        }

        return super.onContextItemSelected(item);
    }

    //清空显示
    private void ClearDisplay() {

        //还原显示框大小
        activityMainBinding.ScanfEditText.setTextSize(40);
        activityMainBinding.PrintfText.setTextSize(30);

        //表示已经按下=后,重新输入数字的情况
        if (GetEqual) {
            GetEqual = false;
            activityMainBinding.ScanfEditText.setText("");
            ret = "";
            //清空储存的内容
            SumNumber.clear();
            Number.setLength(0);

            //还原字体大小
            SIzeOfText = 40;
        }
    }

    //连续计算的情况
    private void ListComputing(String str) {

        if (str.equals(Del)) {
            GetEqual = false;

            //还原显示框大小
            activityMainBinding.ScanfEditText.setTextSize(40);
            activityMainBinding.PrintfText.setTextSize(30);

            SIzeOfText = 40;

            ret = "";

            if (Number.length() > 0) {
                Number.deleteCharAt(Number.length() - 1);
            } else if (SumNumber.size() > 0) {
                try {
                    Number.setLength(0);
                    Number.append(SumNumber.remove(SumNumber.size() - 1));
                    Number.deleteCharAt(Number.length() - 1);
                }catch (NumberFormatException e){
                    Log.d("Number", "出现空值");
                }
            }

        } else if (!ret.equals("Error")){
            GetEqual = false;

            //还原显示框大小
            activityMainBinding.ScanfEditText.setTextSize(40);
            activityMainBinding.PrintfText.setTextSize(30);

            //清空储存的内容
            SumNumber.clear();
            Number.setLength(0);
            //还原字体大小
            SIzeOfText = 40;

            SumNumber.add(ret);
            SumNumber.add(str);

            ret = "";
        }
    }

    //使得按下数字后动态计算结果
    private void DynamicCalculation() {
        if(!SumNumber.isEmpty() && SumNumber.size() > 0){
            //将number的数据放入Sumnumber
            if (!Number.equals("") && Number != null) {
                //保存数据
                try {
                    SumNumber.add(String.valueOf(Number));
                } catch (NumberFormatException e) {
                    Log.d("Number", "出现空值");
                }

            }

            //计算当前结果
            ReversePolish reversePolish = new ReversePolish(SumNumber);
            ret = reversePolish.EvaluatePostfixExpressions();

            //删去暂时存放的数据
            SumNumber.remove(SumNumber.size() - 1);
        }
    }
}


2.2 中缀表达式转后缀表达式,使用逆波兰计算

package com.example.computermoblie;

import android.content.Intent;
import android.util.Log;
import android.view.View;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Stack;

public class ReversePolish {
    public List<String> SumNumber;


    Stack<BigDecimal> SymbolStack = new Stack<>();

    //表示没有计算错误的情况
    private boolean Error = false;

    public static final int LeftBrack = 0;   //左括号优先级
    public static final int AandS = 1;   //加减法
    public static final int MandD = 2;   //乘除
    public static final int RightBrack = 3;   //右括号优先级

    //中缀转后缀
    public Queue<String> InfixToSuffix() {
        Queue<String> queue = new ArrayDeque<>();
        Stack<String> swapStack = new Stack<>();

        for (int i = 0; i < SumNumber.size(); i++) {
            String isStr = SumNumber.get(i);

            if (!IsSymbol(isStr)) {
                queue.add(isStr); // 将数字直接添加到输出队列中
            } else {
                if (swapStack.isEmpty() || isStr.equals("(")) {
                    swapStack.push(isStr);
                } else if (isStr.equals(")")) {
                    if(!swapStack.isEmpty()){
                        while (!swapStack.peek().equals("(")) {
                            queue.add(swapStack.pop());
                        }
                        swapStack.pop(); // 弹出 "("
                    }
                } else {
                    while (!swapStack.isEmpty() && JudgmentPriority(swapStack.peek(), isStr)) {
                        queue.add(swapStack.pop());
                    }
                    swapStack.push(isStr);
                }
            }
        }

        while (!swapStack.isEmpty()) {
            queue.add(swapStack.pop());
        }

        return queue;
    }

    public String EvaluatePostfixExpressions() {
        Error = false;  // 表示运算未发现错误
        BigDecimal ret = null; // 表示最后的运算结果
        Queue<String> queue = InfixToSuffix();  // 获取后缀表达式

        Log.d("WQWQ",queue.toString());

        while (!queue.isEmpty()) {
            String str = queue.remove();

            if (!IsSymbol(str)) {
                //保存数据
                try {
                    BigDecimal number = new BigDecimal(str);
                    SymbolStack.push(number);
                } catch (NumberFormatException e) {
                    Log.d("Number","出现空值");
                }
            } else {
                if (SymbolStack.size() < 2) {
                    Error = true; // 栈中元素不足2个,运算错误
                    break;
                }

                BigDecimal op2 = SymbolStack.pop();
                BigDecimal op1 = SymbolStack.pop();
                BigDecimal result = null;

                switch (str) {
                    case "+":
                        result = op1.add(op2);
                        break;
                    case "-":
                        result = op1.subtract(op2);
                        break;
                    case "×":
                        result = op1.multiply(op2);
                        break;
                    case "÷":
                        if (op2.compareTo(BigDecimal.ZERO) == 0) {
                            Error = true; // 除数为零,运算错误
                            break;
                        }
                        result = op1.divide(op2, 3, RoundingMode.HALF_UP);
                        break;
                    default:
                        Error = true; // 非法的运算符,运算错误
                        break;
                }

                if (Error) {
                    break;
                } else {
                    SymbolStack.push(result);
                }
            }
        }

        if (Error) {
            return "Error"; // 出现错误后直接返回错误信息
        } else {
            if (!SymbolStack.isEmpty()) {
                ret = SymbolStack.pop();
            }
            // 使用toEngineeringString()方法将结果输出为工程计数法
            return ret.toEngineeringString();
        }
    }

    public ReversePolish(List<String> sumNumber) {
        SumNumber = sumNumber;
    }

    //判断是否为符号
    public boolean IsSymbol(String str) {
        boolean isSymbole = false;
        if (str.equals("+")) {
            isSymbole = true;
        } else if (str.equals("-")) {
            isSymbole = true;
        } else if (str.equals("×")) {
            isSymbole = true;
        } else if (str.equals("÷")) {
            isSymbole = true;
        } else if (str.equals("(")) {
            isSymbole = true;
        } else if (str.equals(")")) {
            isSymbole = true;
        }

        return isSymbole;
    }

    //判断优先级
    public boolean JudgmentPriority(String PreantStr, String SunStr) {
        //默认PreantStr优先级小于SunStr
        boolean value = false;

        if (SymbolValue(PreantStr) >= SymbolValue(SunStr)) {
            value = true;
        }

        return value;
    }

    //判断属于什么符号
    public int SymbolValue(String str) {
        int Value = LeftBrack;

        if (str.equals("+")) {
            Value = AandS;
        } else if (str.equals("-")) {
            Value = AandS;
        } else if (str.equals("×")) {
            Value = MandD;
        } else if (str.equals("÷")) {
            Value = MandD;
        } else if (str.equals("(")) {
            Value = LeftBrack;
        } else if (str.equals(")")) {
            Value = RightBrack;
        }
        return Value;
    }

    public List<String> getSumNumber() {
        return SumNumber;
    }
}

主要代码如上,此外笔者代码存在一个空指针异常(NullPointerException)的问题,问题出在SumNumber如果多次使用删除键反复输入数据在删除这种测试操作会导致空指针异常,使得操作SumNumber的代码逻辑访问到空指针。这个问题笔者解决了很久都没找到问题所在,如有找到问题所在烦请告知笔者,不胜感激。具体异常信息如下:

根据日志信息,异常的原因是在某个地方尝试调用一个对象的toString()方法,但该对象为空(null),因此无法执行该方法。

根据提供的堆栈跟踪信息,可以看出空指针异常(NullPointerException)在以下方法中被抛出:

  1. com.example.computermoblie.ReversePolish.InfixToSuffix(ReversePolish.java:45)

    image-20230723174051695

  2. com.example.computermoblie.ReversePolish.EvaluatePostfixExpressions(ReversePolish.java:69)

image-20230723174318764

  1. com.example.computermoblie.MainActivity.onClick(MainActivity.java:189)

image-20230723174451336

  1. com.example.computermoblie.MainActivity.DynamicCalculation(MainActivity.java:872)

image-20230723174428328

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue 学习笔记 【ElementPlus】el-menu 折叠后图标不见了

项目当前版本 {"dependencies": {"element-plus/icons-vue": "^2.1.0","types/js-cookie": "^3.0.3","types/nprogress": "^0.2.0","axios": "^1.4.0","core-js": &quo…

Java - 注解开发

注解开发定义bean Component的衍生注解 Service&#xff1a; 服务层的注解 Repository&#xff1a; 数据层的注解 Controller&#xff1a; 控制层的注解 纯注解开发 bean管理 bean作用范围 在类上面添加Scope(“singleton”) // prototype: 非单例 bean生命周期 PostCon…

推荐用于学习RN原生模块开发的开源库—react-native-ble-manager

如题RN的原生模块/Native Modules的开发是一项很重要的技能&#xff0c;但RN官网的示例又比较简单&#xff0c;然后最近我接触与使用、还有阅读了react-native-ble-manager的部份源码&#xff0c;发现里边完全包含了一个Native Modules所涉及的知识点/技术点&#xff0c;故特推…

java商城系统和php商城系统对比

java商城系统和php商城系统是两种常见的电子商务平台&#xff0c;它们都具有一定的优势和劣势。那么&#xff0c;java商城系统和php商城系统又有哪些差异呢&#xff1f; 一、开发难度 Java商城系统和PHP商城系统在开发难度方面存在一定的差异。Java商城系统需要使用Java语言进…

jenkins执行jmeter时,报Begin size 1 is not equal to fixed size 5

jenkins执行jmeter脚本的时候一直提示如下错误&#xff1a; Tidying up ... Fri Jul 28 17:03:53 CST 2023 (1690535033178) Error generating the report: org.apache.jmeter.report.dashboard.GenerationException: Error while processing samples: Consumer failed wi…

WEB:wife_wife

背景知识 JavaScript原型链污染 题目 先尝试一下&#xff0c;注册了管理员账号 这里不知道邀请码&#xff0c;所以没有勾选 答案不正确 这里借鉴其他大佬的思路 查看源代码才知道&#xff0c;后端没有数据库&#xff0c;所以sql注入是不可能的 // post请求的路径 app.pos…

qemu搭建arm环境以及文件共享

几乎完全参照该文章 使用QEMU搭建ARM64实验环境 - 简书 ubuntu 14.04&#xff0c;linux3.16&#xff0c; busybox-1.31.0 arm-linux-gnueabi-gcc -v linux3.16以及busybox下载安装可参考链接 Ubuntu14.04安装qemu&#xff0c;运行linux-3.16gdb调试_qemu 安装 ubuntu 14_这个我…

Redis—相关背景

Redis—相关背景 &#x1f50e;Redis—特性In-memory data structures—在内存中存储数据Programmability—可编程性Extensibility—可扩展性Persistence—持久化Clustering—集群High availability—高可用 &#x1f50e;Redis 为什么快&#x1f50e;Redis 的使用场景Real-tim…

性能测试Ⅲ

JMeter里面使用后端监听器&#xff0c;结合influxdb的时序数据库以及grafana可以打造性能测试的平台 后端监听器&#xff1a;把JMeter执行过程中的数据写到influxDB的时序数据库 influxD&#xff1a;时序数据库&#xff0c;用来存储JMeter发送请求的数据 Grafana &#xff1a;从…

vue3+ts+elementui-plus二次封装树形表格

复制粘贴即可&#xff1a; 一、定义table组件 <template><div classmain><div><el-table ref"multipleTableRef" :height"height" :default-expand-all"isExpend" :data"treeTableData"style"width: 100%…

CAN总线开发必看! 如何使用CANlib检测CAN帧溢出情况? Kvaser三招帮你轻松解决

从1980年代&#xff0c;Kvaser就开始CAN产品的研发&#xff0c;在相关产品开发领域有近40多年的经验&#xff0c;对CAN和相关总线技术有着非常深入的研究。广州智维电子科技是KVASER的中国引进者&#xff0c;我们会不定期分享一些有趣的发现和特定情况的技术处理。 在开发严重…

600 条最强 Linux 命令总结

今天&#xff0c;带来一篇 Linux 命令总结的非常全的文章&#xff0c;也是我们平时工作中使用率非常高的操作命令&#xff0c;命令有点多&#xff0c;建议小伙伴们可以先收藏后阅读。 1. 基本命令 uname -m 显示机器的处理器架构 uname -r 显示正在使用的内核版本 dmidecode -…

【LeetCode】102.二叉树的层序遍历

题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例 2&#xff1a; …

MySQL基础(四)数据库备份

目录 前言 一、概述 1.数据备份的重要性 2.造成数据丢失的原因 二、备份类型 &#xff08;一&#xff09;、物理与逻辑角度 1.物理备份 2.逻辑备份 &#xff08;二&#xff09;、数据库备份策略角度 1.完整备份 2.增量备份 三、常见的备份方法 四、备份&#xff08…

自动驾驶技术架构

自动驾驶技术架构 自动驾驶技术架构 自动驾驶关键技术 自动驾驶汽车技术架构较为复杂&#xff0c;涉及了多领域的交叉互容&#xff0c;例如汽车、交通、通信等&#xff0c;基于自动驾驶相关的软硬件、辅助开发工具、行业标准等各方面关键问题&#xff0c;自动驾驶汽车关键技术…

教育机构视频播放时观看行为分析有哪些应用?

教育机构视频播放时观看行为分析有哪些应用&#xff1f; 观看行为分析 观看行为分析是指我们平台基于视频大数据分析&#xff0c;能够以秒为粒度展示观众如何观看您的视频。 视频观看热力图是单次观看行为的图形化表示&#xff0c;我们平台云点播视频的每一次播放&#xff0…

【一天三道算法题】代码随想录——Day14

一. 有效的括号 题目链接&#xff1a;力扣 思路&#xff1a;无非三种情况&#xff1a; 1. 左侧括号多&#xff0c;右侧少 2. 左右侧一样多&#xff0c;该字符串属于有小括号字符串 3. 右侧括号多&#xff0c;左侧少 那么说白了就是要比较左右括号的数量&#xff0c;谁多&…

行业追踪,2023-07-28

自动复盘 2023-07-28 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

图片转pdf手机版免费?这几款转换软件看看

图片转pdf手机版免费&#xff1f;将图片转换成PDF文件可以带来很多好处。首先&#xff0c;PDF文件可以更好地保护你的图片。相对于图片文件&#xff0c;PDF文件更难以编辑和改变&#xff0c;因此更适合用于存储重要的图片。其次&#xff0c;将多张图片合并成一个PDF文件可以更好…

《面试1v1》Kafka与传统消息系统区别

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…