[JAVA] I made a calculator app on Android

Overview

It is a simple calculator app. I made it for studying Android.

Android Studio 3.6.2 TableLayout caluculation.PNG

Ingenuity / difficulty

-Create a button that straddles columns in TableLayout Nested LinearLayout inside the Table row.

・ Display images only under specific conditions Changed to set the image in imageView with setImageResource.

・ Processing that prioritizes multiplication and division Store the calculation formula in ArrayList → Search for × ÷ and perform priority calculation → Delete the calculated part from the list → Add the calculation result to the list → Repeat until × ÷ disappears → Then perform + -calculation I implemented it by the method.

・ Lose the calculation error of double The problem that "1.0d --0.9d = 0.099999999 ..." is displayed. I solved it using the BigDecimal class.

・ An error will occur when the division is not divisible. BigDecimal causes an ArithmeticException when a number that is not divisible by division (recurring decimal) appears. To avoid this error, the number with 11 decimal places is rounded off. However, this time, there is a problem that even when the number is divisible, it is displayed up to the 10th decimal place. It will be like this → 4/2 = 2.0000000000 To avoid this, the division is enclosed in try-catch and the number with 11 decimal places is rounded only when an ArithmeticException occurs.

・ Bug fix Avoid typing multiple decimal points. Do not hit +-× ÷ = in an unintended place. = Various behaviors after clicking the button. There were many other things ...

How to create a cross-column button in TableLayout

Nest the LinearLayout inside the Table row.

activity_main.xml


<TableRow
        android:id="@+id/row2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="2">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <Button
                android:id="@+id/button4"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="@string/button4"
                android:textSize="25sp"
                android:onClick="btnCurrent_onClick"/>

            <Button
                android:id="@+id/button1"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="@string/button1"
                android:textSize="25sp"
                android:onClick="btnCurrent_onClick"/>

        </LinearLayout>

        <!--Button across lines-->
        <Button
            android:id="@+id/buttonPlus"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:background="#FFBF00"
            android:text="@string/buttonPlus"
            android:textSize="25sp"
            android:onClick="btnCurrent_onClick"/>
</TableRow>

        

Impressions / reflection

I learned a lot because I couldn't understand until I made it. I will continue to learn in the cycle of reading a book → trying to make it.

The point of reflection is that it is full of if statements. I want to write cleaner code.

Full code

MainActivity.java


package to.msn.wings.caluculator;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {

    List<String> stringList = new ArrayList<>();//List to store input characters
    int decimalPointCount = 0; //Variable to prevent continuous clicks on the decimal point button.
    int ClickedFormulaOnce = 0; // +-/*For determining whether even one is included in the calculation formula.+-*/Because it cannot be calculated without even one.
    int formulaContinuousClick = 0; // +-/*Variable to prevent continuous clicks on the button.

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

    //Calculation method
    public void calculation(TextView txt) {
        //Get all the characters of TextView and store them in the array.
        String txtAll = txt.getText().toString();

        //Regular expression that also includes the delimiter itself in the array
        //Regular expressions((?<=[+×÷-])|(?=[+×÷-]))The meaning of+-It means to separate immediately before and after × ÷.
        String[] stringArray = txtAll.split("((?<=[+×÷-])|(?=[+×÷-]))", 0);

        //After storing in the array, delete all the characters in TextView.
        txt.setText(null);
        //Store all arrays in ArrayList.
        for(String s:stringArray) {
            stringList.add(s);
        }
        //Big Decimal has no error unlike double.
        BigDecimal bigDecimalResultValue = new BigDecimal("0.0");
        //Multiplication division processing
        for(int i = 1; i < stringList.size(); i += 2) {
            if(stringList.get(i).equals("×")) {
                bigDecimalResultValue = new BigDecimal(stringList.get(i-1)).multiply(new BigDecimal(stringList.get(i+1)));
                //Remove the calculated numbers and expressions from the stringList. Example: "2*3+"2" of "1"*Delete the part of "3".
                stringList.remove(i-1);
                stringList.remove(i-1);
                stringList.remove(i-1);
                //Add the calculation result to stringList. Example: "2*3+1 "to" 6+Set to 1 ".
                stringList.add(i-1, String.valueOf(bigDecimalResultValue));
                //Since we deleted 3 stringLists and added 1 to them, subtract 2 from i.
                i -= 2;
            } else if (stringList.get(i).equals("÷")) {
                //When the division of Bigdecimal is an indivisible number, an ArithmeticException error occurs. Therefore, enclose it in trycath.
                //When this is finally divisible, 00000 is not wasted after the decimal point.
                //Round the 11th decimal place only when it is not divisible.
                try {
                    bigDecimalResultValue = new BigDecimal(stringList.get(i-1)).divide(new BigDecimal(stringList.get(i+1)));
                } catch (ArithmeticException e) {
                    bigDecimalResultValue = new BigDecimal(stringList.get(i-1)).divide(new BigDecimal(stringList.get(i+1)), 10, RoundingMode.HALF_UP);//Rounded. Display up to 10 decimal places.
                }
                stringList.remove(i-1);
                stringList.remove(i-1);
                stringList.remove(i-1);
                stringList.add(i-1, String.valueOf(bigDecimalResultValue));
                i -= 2;
            }
        }
        //Addition and subtraction processing
        //Multiplication and division have already been processed, so simply add and subtract in order from the front.
        while(stringList.size() > 1) {
            if(stringList.get(1).equals("+")) {
                bigDecimalResultValue = new BigDecimal(stringList.get(0)).add(new BigDecimal(stringList.get(2)));
                stringList.remove(0);
                stringList.remove(0);
                stringList.remove(0);
                stringList.add(0, String.valueOf(bigDecimalResultValue));
            } else if (stringList.get(1).equals("-")) {
                bigDecimalResultValue = new BigDecimal(stringList.get(0)).subtract(new BigDecimal(stringList.get(2)));
                stringList.remove(0);
                stringList.remove(0);
                stringList.remove(0);
                stringList.add(0, String.valueOf(bigDecimalResultValue));
            }
        }
        if(String.valueOf(bigDecimalResultValue).equals("3")) {
            //Processing to display the image only when the result is 3
            //Get ImageView object based on ID
            @SuppressLint("ResourceType")
            ImageView iv = this.findViewById(R.id.imageView);
            //Set the image in the drawable folder
            iv.setImageResource(R.drawable.nabeatsu);
            txt.setText("World pans");
        } else {
            txt.setText(String.valueOf(bigDecimalResultValue));
        }
        //Clear the list after displaying the results.
        stringList.clear();
    }
    public void btnCurrent_onClick(View view) {
        //Get text view
        TextView txt = findViewById(R.id.textView);
        //Judge the button clicked by the switch statement. Display in text.
        switch (view.getId()) {
            case R.id.button0:
                txt.append("0");
                formulaContinuousClick = 0;
                break;
            case R.id.button1:
                txt.append("1");
                formulaContinuousClick = 0;
                break;
            case R.id.button2:
                txt.append("2");
                formulaContinuousClick = 0;
                break;
            case R.id.button3:
                txt.append("3");
                formulaContinuousClick = 0;
                break;
            case R.id.button4:
                txt.append("4");
                formulaContinuousClick = 0;
                break;
            case R.id.button5:
                txt.append("5");
                formulaContinuousClick = 0;
                break;
            case R.id.button6:
                txt.append("6");
                formulaContinuousClick = 0;
                break;
            case R.id.button7:
                txt.append("7");
                formulaContinuousClick = 0;
                break;
            case R.id.button8:
                txt.append("8");
                formulaContinuousClick = 0;
                break;
            case R.id.button9:
                txt.append("9");
                formulaContinuousClick = 0;
                break;

            case R.id.buttonBS:
                formulaContinuousClick = 0;
                //Get Editable instance
                Editable editable = Editable.Factory.getInstance().newEditable(txt.getText());

                //Processing to delete the last character each time the button is pressed
                if(editable.length() > 0){
                    //The first argument of delete is start of the character you want to delete,The second argument is the end of the character you want to delete
                    editable.delete(editable.length()-1, editable.length());
                }
                //Set in TextView
                txt.setText(editable, TextView.BufferType.EDITABLE);

                break;

            case R.id.buttonClear:
                decimalPointCount = 0;
                ClickedFormulaOnce = 0;
                formulaContinuousClick = 0;
                stringList.clear();

                //For clearing the image
                @SuppressLint("ResourceType")
                ImageView iv = this.findViewById(R.id.imageView);
                iv.setImageDrawable(null);
                txt.setText(null);
                break;

            case R.id.buttonPoint:
                //Judgment that prevents repeated decimal points.
                if (decimalPointCount == 0) {
                    txt.append(".");
                    decimalPointCount = 1;
                }
                break;

            //From here+-/*What happens when you click.
            //formulaContinuousClick+-*/=For preventing continuous clicks.
            //Clicked Formula Once+-*/For determining whether you clicked even once.
            case R.id.buttonPlus:
                formulaContinuousClick++;
                // +-/*Processing when you press. Ignore for continuous taps.
                //Also, if there is nothing in TextView, it will be ignored.
                if(formulaContinuousClick == 1 && !(txt.getText().toString().equals(""))) {
                    ClickedFormulaOnce = 1;
                    txt.append("+");
                }
                decimalPointCount = 0; //Returns the decimal point click count to 0.
                break;

            case R.id.buttonMinus:
                formulaContinuousClick++;
                if(formulaContinuousClick == 1 && !(txt.getText().toString().equals(""))) {
                    ClickedFormulaOnce = 1;
                    txt.append("-");
                }
                decimalPointCount = 0;
                break;

            case R.id.buttonMulti:
                formulaContinuousClick++;
                ClickedFormulaOnce = 1;
                if(formulaContinuousClick == 1 && !(txt.getText().toString().equals(""))) {
                    ClickedFormulaOnce = 1;
                    txt.append("×");
                }
                decimalPointCount = 0;
                break;

            case R.id.buttonDiv:
                formulaContinuousClick++;
                ClickedFormulaOnce = 1;
                if(formulaContinuousClick == 1 && !(txt.getText().toString().equals(""))) {
                    ClickedFormulaOnce = 1;
                    txt.append("÷");
                }
                decimalPointCount = 0;
                break;

            case R.id.buttonEqual:
                if(ClickedFormulaOnce == 1) {
                    formulaContinuousClick++;
                }
                if (ClickedFormulaOnce == 1 && formulaContinuousClick == 1) {
                    formulaContinuousClick = 0;
                    ClickedFormulaOnce = 0;
                    //Prevents additional decimal points when the calculation result has a decimal point. Example "3.3+0.1=3.4 → Click the decimal point → "3".4."Such
                    decimalPointCount = 1;
                    if(txt.getText().toString().length() > 56) {
                        Context context = getApplicationContext();
                        Toast.makeText(context, "The number of characters exceeds the upper limit of 56 characters.", Toast.LENGTH_LONG).show();
                    } else {
                        calculation(txt);
                    }
                }
                break;
        }
    }
}

activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:shrinkColumns="0,1,2,3,4">


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:textSize="50sp" />

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal" />
    </LinearLayout>


    <TableRow
        android:id="@+id/row1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="2">

        <Button
            android:id="@+id/button7"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:onClick="btnCurrent_onClick"
            android:text="@string/button7"
            android:textSize="25sp" />

        <Button
            android:id="@+id/button8"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:onClick="btnCurrent_onClick"
            android:text="@string/button8"
            android:textSize="25sp" />

        <Button
            android:id="@+id/button9"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:onClick="btnCurrent_onClick"
            android:text="@string/button9"
            android:textSize="25sp" />

        <Button
            android:id="@+id/buttonDiv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:background="#FFBF00"
            android:onClick="btnCurrent_onClick"
            android:text="@string/buttonDiv"
            android:textSize="25sp" />

        <Button
            android:id="@+id/buttonClear"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:background="#FF4000"
            android:onClick="btnCurrent_onClick"
            android:text="@string/buttonClear"
            android:textSize="25sp" />
    </TableRow>

    <TableRow
        android:id="@+id/row2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="2">

        <Button
            android:id="@+id/button4"
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:onClick="btnCurrent_onClick"
            android:text="@string/button4"
            android:textSize="25sp" />

        <Button
            android:id="@+id/button5"
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:onClick="btnCurrent_onClick"
            android:text="@string/button5"
            android:textSize="25sp" />


        <Button
            android:id="@+id/button6"
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:onClick="btnCurrent_onClick"
            android:text="@string/button6"
            android:textSize="25sp" />

        <Button
            android:id="@+id/buttonMulti"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"

            android:background="#FFBF00"
            android:onClick="btnCurrent_onClick"
            android:text="@string/buttonMulti"
            android:textSize="25sp" />

        <Button
            android:id="@+id/buttonBS"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"

            android:background="#00ffff"
            android:onClick="btnCurrent_onClick"
            android:text="@string/buttonBS"
            android:textSize="25sp" />
    </TableRow>

    <TableRow
        android:id="@+id/row3"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="2">

        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:onClick="btnCurrent_onClick"
            android:text="@string/button1"
            android:textSize="25sp" />

        <Button
            android:id="@+id/button2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:onClick="btnCurrent_onClick"
            android:text="@string/button2"
            android:textSize="25sp" />


        <Button
            android:id="@+id/button3"
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:onClick="btnCurrent_onClick"
            android:text="@string/button3"
            android:textSize="25sp" />

        <Button
            android:id="@+id/buttonPlus"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:background="#FFBF00"
            android:onClick="btnCurrent_onClick"
            android:text="@string/buttonPlus"
            android:textSize="25sp" />


        <Button
            android:id="@+id/buttonMinus"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"

            android:background="#FFBF00"
            android:onClick="btnCurrent_onClick"
            android:text="@string/buttonMinus"
            android:textSize="40sp" />
    </TableRow>


    <TableRow
        android:id="@+id/row4"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <Button
            android:id="@+id/button0"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_span="2"
            android:onClick="btnCurrent_onClick"
            android:text="@string/button0"
            android:textSize="25sp" />

        <Button
            android:id="@+id/buttonPoint"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:onClick="btnCurrent_onClick"
            android:text="@string/buttonPoint"
            android:textSize="40sp" />

        <Button
            android:id="@+id/buttonEqual"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:layout_span="2"
            android:background="#2EFE64"
            android:onClick="btnCurrent_onClick"
            android:text="@string/buttonEqual"
            android:textSize="25sp" />
    </TableRow>

string.xml


<resources>
    <string name="app_name">Caluculator</string>
    <string name="button0">0</string>
    <string name="button1">1</string>
    <string name="button2">2</string>
    <string name="button3">3</string>
    <string name="button4">4</string>
    <string name="button5">5</string>
    <string name="button6">6</string>
    <string name="button7">7</string>
    <string name="button8">8</string>
    <string name="button9">9</string>
    <string name="buttonPlus">+</string>
    <string name="buttonMinus">-</string>
    <string name="buttonMulti">×</string>
    <string name="buttonDiv">÷</string>
    <string name="buttonPoint">.</string>
    <string name="buttonEqual">=</string>
    <string name="buttonClear">C</string>
    <string name="buttonBS">BS</string>
</resources>

Recommended Posts

I made a calculator app on Android
I made a matching app (Android app)
[Android] I made a pedometer app.
I made a rock-paper-scissors app with android
I made a chat app.
I made a library for displaying tutorials on Android.
I made a shopify app @java
I made a rock-paper-scissors app with kotlin
I made an Android app for MiRm service
I made a viewer app that displays a PDF
I made a portfolio with Ruby On Rails
ROS app development on Android
I made a drawing chat "8bit paint chat" on WebAssembly
I made a lock pattern using the volume key with the Android app. Fragment edition
I tried adding a separator line to TabLayout on Android
I made a GUI with Swing
Notes on calling Installer on Android App
I made a package.xml generation tool.
[Rails] I made a simple calendar mini app with customized specifications.
I tried to create a simple map app in Android Studio
I made a mistake when installing VLC on Ubuntu 18.04 via snap
I recently made a js app in the rumored Dart language
[Ruby] I made a simple Ping client
Try deploying a Rails app on EC2-Part 1-
I made a risky die with Ruby
I made a plugin for IntelliJ IDEA
Try making a calculator app in Java
Deploy a Java web app on Heroku
I made a new Java deployment tool
I made a bulletin board using Docker 1
I have a question about Android studio.
Allows Youtube autoplay on Cordova's Android app
I made a site that summarizes information on carbohydrate restriction with Vue.js
I made a Diff tool for Java files
I made a primality test program in Java
[Stajyun also admitted] I want a gourmet spy, but it costs 1103.3543 trillion yen, so I made an android app
I made StringUtils.isBlank
04. I made a front end with SpringBoot + Thymeleaf
I made a mosaic art with Pokemon images
I made an app for myself! (Reading management app)
I made a gender selection column with enum
Publish the app made with ruby on rails
I want to play a GIF image on the Andorid app (Java, Kotlin)
Build a streaming server on your iOS app
I made a rock-paper-scissors game in Java (CLI)
I tried to create a LINE clone app
I made a Docker container to run Maven
I made a Ruby extension library in C
I stumbled on Android DataBinding + Kotlin (more BindingAdapter)
[Rails] I made a draft function using enum
I tried running Ansible on a Docker container
Android: I had a hard time displaying the HTML file on the SD card
I made a simple graph library for smartphone apps [MP Android Chart Kai]
I made a LINE bot with Rails + heroku
I tried running Java on a Mac terminal
Since I use it often, I make a note of DB related things on Android.
I tried deploying a page made with antique Middleman on Azure Static Web Apps
I have a question. I get an error when playing a video in Listview on android.
I made a Docker image of SDAPS for Japanese
I tried using a database connection in Android development
I made a simple calculation problem game in Java