Home » Programming » JAVA » Simple Calculator Java Tutorial

Android Simple Calculator Java Tutorial

In this article, you will learn to make calculator app in Android Studio using Java Programming Language. This tutorial uses expj4 library for arithmetic expression. Follow below steps to make simple calculator app in android studio using java:

Step 1:

First create a empty project in Android Studio with an application name: “Simple Calculator” and package name as “com.example.simplecalculator”.

Step 2:

Add the exp4j dependency in app → build.gradle file as show below. This library is used to evaluate the arithmetic expressions.

 implementation 'net.objecthunter:exp4j:0.4.4'

Step 3:

Open the app → src → main → res → values → strings.xml file and add following code. These strings used in step 6.

   <string name="clear_text">C</string>
    <string name="del_text">-></string>
    <string name="power_text">x<sup>n</sup></string>
    <string name="percent_text">%</string>
    <string name="multiply_text">*</string>
    <string name="divide_text">/</string>
    <string name="add_text">+</string>
    <string name="subtraction_text">-</string>
    <string name="equal_text">=</string>
    <string name="one_text">1</string>
    <string name="two_text">2</string>
    <string name="three_text">3</string>
    <string name="four_text">4</string>
    <string name="five_text">5</string>
    <string name="six_text">6</string>
    <string name="seven_text">7</string>
    <string name="eight_text">8</string>
    <string name="nine_text">9</string>
    <string name="zero_text">0</string>
    <string name="dualzero_text">00</string>
    <string name="dot_text">.</string>

Step 4:

Now right click on the app → src → main → res → drawable folder and create new → Drawable Resource File as the File name: “button”.

Step 5:

After add below lines in button.xml file. This drawable resource file is used to style the buttons of the calculator.

<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>
            <gradient android:angle="90" android:endColor="#FFFFFF" android:startColor="#9EB8FF" android:type="linear" />
            <padding android:bottom="0dp" android:left="0dp" android:right="0dp" android:top="0dp" />
            <size android:width="60dp" android:height="60dp" />
            <stroke android:width="1dp" android:color="#ff3da6ef" />
        </shape>
    </item>
    <item>
        <shape>
            <gradient android:angle="90" android:endColor="#FFFFFF" android:startColor="#ffd9d9d9" android:type="linear" />
            <padding android:bottom="0dp" android:left="0dp" android:right="0dp" android:top="0dp" />
            <size android:width="60dp" android:height="60dp" />
            <stroke android:width="0.5dp" android:color="#ffcecece" />
        </shape>
    </item>
</selector>

Step 6:

Replace the content of app → src → main → res → layout → activity_main.xml file by following code. This code creates a TextView as the calculator input/output screen and some necessary buttons.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">


    <TextView
        android:id="@+id/ioScreen"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:fontFamily="serif"
        android:gravity="bottom|end"
        android:maxLength="32"
        android:padding="14dp"
        android:textSize="30sp"
        android:typeface="normal" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/ioScreen"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btnClear"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/clear_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnDel"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/del_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnPower"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/power_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnPercent"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/percent_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btnSeven"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/seven_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnEight"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/eight_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnNine"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/nine_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnDivide"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/divide_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btnFour"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/four_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnFive"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/five_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnSix"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/six_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnMultiply"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/multiply_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btnOne"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/one_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnTwo"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/two_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnThree"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/three_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnSubtract"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/subtraction_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btnDot"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/dot_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnZero"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/zero_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btn00"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/dualzero_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />

            <Button
                android:id="@+id/btnAdd"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/button"
                android:fontFamily="serif"
                android:text="@string/add_text"
                android:textAllCaps="false"
                android:textSize="30sp"
                android:typeface="monospace" />
        </LinearLayout>

        <Button
            android:id="@+id/btnEqual"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@drawable/button"
            android:fontFamily="serif"
            android:text="@string/equal_text"
            android:textAllCaps="false"
            android:textSize="30sp"
            android:typeface="monospace" />


    </LinearLayout>
</RelativeLayout>

Step 7:

Replace the content of app → src → java → your package name → MainActivity.java file to following code. Complete description of following code is provided in comments of the following code.

package com.example.simplecalculator;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;

public class MainActivity extends AppCompatActivity {
    // IDs of all the numeric buttons
    private int[] numericButtons = {R.id.btn00, R.id.btnZero, R.id.btnOne, R.id.btnTwo, R.id.btnThree, R.id.btnFour, R.id.btnFive, R.id.btnSix, R.id.btnSeven, R.id.btnEight, R.id.btnNine};
    // IDs of all the operator buttons
    private int[] operatorButtons = {R.id.btnAdd, R.id.btnSubtract, R.id.btnMultiply, R.id.btnDivide, R.id.btnPercent, R.id.btnPower};
    // TextView used to display the output
    private TextView txtScreen;
    // Represent whether the lastly pressed key is numeric or not
    private boolean lastNumeric;
    // Represent that current state is in error or not
    private boolean stateError;
    // If true, do not allow to add another DOT
    private boolean lastDot;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Find the TextView
        this.txtScreen = (TextView) findViewById(R.id.ioScreen);
        // Find and set OnClickListener to numeric buttons
        setNumericOnClickListener();
        // Find and set OnClickListener to operator buttons, equal button and decimal point button
        setOperatorOnClickListener();
    }

    /**
     * Find and set OnClickListener to numeric buttons.
     */
    private void setNumericOnClickListener() {
        // Create a common OnClickListener
        View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Just append/set the text of clicked button
                Button button = (Button) v;
                if (stateError) {
                    // If current state is Error, replace the error message
                    txtScreen.setText(button.getText());
                    stateError = false;
                } else {
                    // If not, already there is a valid expression so append to it
                    txtScreen.append(button.getText());
                }
                // Set the flag
                lastNumeric = true;
            }
        };
        // Assign the listener to all the numeric buttons
        for (int id : numericButtons) {
            findViewById(id).setOnClickListener(listener);
        }
    }

    /**
     * Find and set OnClickListener to operator buttons, equal button and decimal point button.
     */
    private void setOperatorOnClickListener() {
        // Create a common OnClickListener for operators
        View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // If the current state is Error do not append the operator
                // If the last input is number only, append the operator
                if (lastNumeric && !stateError) {
                    Button button = (Button) v;
                    if(button.getId() == R.id.btnPower) {
                        txtScreen.append("^");
                    } else {
                        txtScreen.append(button.getText());
                    }
                    lastNumeric = false;
                    lastDot = false;    // Reset the DOT flag
                }
            }
        };
        // Assign the listener to all the operator buttons
        for (int id : operatorButtons) {
            findViewById(id).setOnClickListener(listener);
        }
        // Decimal point
        findViewById(R.id.btnDot).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (lastNumeric && !stateError && !lastDot) {
                    txtScreen.append(".");
                    lastNumeric = false;
                    lastDot = true;
                }
            }
        });

        // Back Button
        findViewById(R.id.btnDel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String str = txtScreen.getText().toString();
                if (str.length() > 1) {
                    str = str.substring(0, str.length() - 1);
                    txtScreen.setText(str);
                    lastNumeric = true;
                } else if (str.length() <= 1) {
                    txtScreen.setText("");
                    lastNumeric = false;
                }
                lastDot = false;
                stateError = false;
            }
            });

        // Clear button
        findViewById(R.id.btnClear).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                txtScreen.setText("");  // Clear the screen
                // Reset all the states and flags
                lastNumeric = false;
                stateError = false;
                lastDot = false;
            }
        });
        // Equal button
        findViewById(R.id.btnEqual).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onEqual();
            }
        });
    }

    /**
     * Logic to calculate the solution.
     */
    private void onEqual() {
        // If the current state is error, nothing to do.
        // If the last input is a number only, solution can be found.
        if (lastNumeric && !stateError) {
            // Read the expression
            String txt = txtScreen.getText().toString();
            // Create an Expression (A class from exp4j library)
            Expression expression = new ExpressionBuilder(txt).build();
            try {
                // Calculate the result and display
                double result = expression.evaluate();
                txtScreen.setText(Double.toString(result));
                lastDot = true; // Result contains a dot
            } catch (ArithmeticException ex) {
                // Display an error message
                txtScreen.setText("Error");
                stateError = true;
                lastNumeric = false;
            }
        }
    }
}

Step 8:

Save all the changes and run the application.

Conclusion

Purpose of this tutorial is providing a basic knowledge to develop a simple calculator application in Android. If you found any bug in the code Please comment below and I will try my best to fix them as soon as possible.

Leave a Reply

Your email address will not be published. Required fields are marked *