Android: Simple Calculator

This tutorial guide you to develop a basic Calculator Android application in Android Studio.

Step 1:
Create a new Android application project with an application name: “Calculator” and package name: “com.javahelps.calculator”.

Step 2:
By default Android uses a green Android robot icon. In this project, we are going to use a custom application icon. Therefore, delete the default ic_launcher icon set from the “mipmap” folder.


Step 3:
Get any PNG image file for the application icon. (It is recommended to have a minimum size 256x256 pixels). This icon is used to display in the Google Play as well as in the applications menu of Android devices.

Step 4:
Right click on the “mipmap” folder and select New → Image Asset


Step 5:
Browse and select your icon as the image file and click on Next → Finish buttons. (Make sure that the resource name is: ic_launcher)


Step 6:
Replace the content of activity_main.xml file by the following code. This code creates a TextView as the calculator number screen and some necessary buttons. TextView is used instead of EditText, in order to prevent manual user input using the default keypad of Android. In this code, some common properties of Buttons are not provided to reduce the length of this tutorial. In your code make sure that you have included these four attributes for all the Buttons.
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="30sp"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/txtScreen"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:gravity="right|center_vertical"
        android:maxLength="16"
        android:padding="10dp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textSize="30sp"
        android:typeface="serif" />

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

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <Button
                android:id="@+id/btnSeven"
                android:text="7" />
            <Button
                android:id="@+id/btnEight"
                android:text="8" />
            <Button
                android:id="@+id/btnNine"
                android:text="9"/>
            <Button
                android:id="@+id/btnDivide"
                android:text="/"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <Button
                android:id="@+id/btnFour"
                android:text="4"/>
            <Button
                android:id="@+id/btnFive"
                android:text="5" />
            <Button
                android:id="@+id/btnSix"
                android:text="6" />
            <Button
                android:id="@+id/btnMultiply"
                android:text="*" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <Button
                android:id="@+id/btnOne"
                android:text="1" />
            <Button
                android:id="@+id/btnTwo"
                android:text="2" />
            <Button
                android:id="@+id/btnThree"
                android:text="3" />
            <Button
                android:id="@+id/btnSubtract"
                android:text="-" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <Button
                android:id="@+id/btnDot"
                android:text="." />
            <Button
                android:id="@+id/btnZero"
                android:text="0" />
            <Button
                android:id="@+id/btnClear"
                android:text="C" />
            <Button
                android:id="@+id/btnAdd"
                android:text="+" />
        </LinearLayout>

        <Button
            android:id="@+id/btnEqual"
            android:text="=" />
    </LinearLayout>
</RelativeLayout>
Step 7:
Right click on the “drawable” folder and select New → Drawable resource file.


Step 8:
Create a drawable file with a name button.


Step 9:
Replace the content of button.xml by the following code. This drawable resource is used to decorate the buttons of the calculator. There are two gradient shapes in this code; one is for button pressed state and another for normal state.
<?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 10:
For all the buttons in the activity_main.xml, add a property “android:background”.
android:background="@drawable/button"
After the modification, activity_main.xml must be like this.

Step 11:
To evaluate the arithmetic expressions, exp4J library is used in this project. Open the “build.gradle (Module: app)” file from the Gradle scripts. Add a dependency 'net.objecthunter:exp4j:0.4.4' to the project as shown below.
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'net.objecthunter:exp4j:0.4.4'
}
Once you save the file, Android Studio will ask to sync the project. Allow it to sync by clicking on the link appeared on top left corner. (You need an active Internet connection to download the libraries by Gradle)


Step 12:
Modify the MainActivity.java as provided below. Complete description about the code is provided in comments.
package com.javahelps.calculator;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
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 ActionBarActivity {
    // IDs of all the numeric buttons
    private int[] numericButtons = {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};
    // 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.txtScreen);
        // 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;
                    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;
                }
            }
        });
        // 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 13:
Save all the changes and run the application.


Note:
Purpose of this tutorial and the project is not developing a perfect Calculator, but providing a basic knowledge to develop a simple application in Android. The application has not been tested completely, so if there are any bugs, please comment below and I will try my best to fix them as soon as possible.

Find the project at Git Hub.
Previous
Next Post »

29 comments

Write comments
jerofad
AUTHOR
January 11, 2016 at 8:44 AM delete

Hello Thanks for this tutorial. But I am having a Runtime exception at:

setNumericOnClickListener();

for (int id : numericButtons) {
findViewById(id).setOnClickListener(listener);
}

setOperatorOnClickListener();

for (int id : operatorButtons) {
findViewById(id).setOnClickListener(listener);
}

Reply
avatar
jerofad
AUTHOR
January 11, 2016 at 9:40 AM delete

Sorry It was my mistake. I have the solution now.

Reply
avatar
Md. Abul Hasnat
AUTHOR
February 11, 2016 at 2:14 AM delete

help please

Reply
avatar
Avinash Bg
AUTHOR
March 14, 2016 at 1:36 PM delete

Javahelps is such a wonderful site.
This tutorial was very helpful to build my basics. I was able to build my own app for Play store. Thank you Sir.

App Link : https://goo.gl/oMlqmn

Reply
avatar
Matthew Ilagan
AUTHOR
April 6, 2016 at 9:58 AM delete

Thank you for your tutorials. They helped me on following my first steps to learning android development. The only problem I encountered was on your main_activity.xml code where it is missing a linear layout for the equals row. Other than that, if anyone copies the code and follows the instructions, then you'll be able to output the app to your phone. Thank you.

Reply
avatar
Nauman Idrees
AUTHOR
July 12, 2016 at 10:56 PM delete

Helllooooo Sir !!!..................I have faced a problem in the evaluation of expression....... For example, 2+5 and 2-5 is working well, but 2*5 and 2/5 is not working, "app not responding" error.........Can u plz help me??

Reply
avatar
Gobinath
AUTHOR
July 13, 2016 at 9:46 AM delete

Hi,
I am unable to reproduce the error in my computer. Could you please share the logcat error log when you get the error?

Reply
avatar
Nauman Idrees
AUTHOR
July 15, 2016 at 10:15 AM delete

https://uploads.disquscdn.com/images/ce41abc7d5cb47b81336b228ee36d8f2155c511b7bba447ae8bb020bf10c0818.png

Reply
avatar
Nauman Idrees
AUTHOR
July 15, 2016 at 10:16 AM delete

this is the logcat.....

Reply
avatar
Gobinath
AUTHOR
July 15, 2016 at 2:17 PM delete

Hi,
Make sure that you are using / for division (not ÷) and * for multiplication (not x). If it does not fix your problem, feel free to comment below :-)

Reply
avatar
Nauman Idrees
AUTHOR
July 15, 2016 at 3:58 PM delete

Thank You sir !! :) Issue has been resolved.............But i don't understand how these signs (÷ , x) affect it's working. Can you please understand me.

Reply
avatar
Gobinath
AUTHOR
July 16, 2016 at 6:38 AM delete

Hi,
Here the problem is with the exp4j library which is used to evaluate the input. This library does not support those characters. However, if you still want to use those characters for better UI design, replace all '÷' by '/' and 'x' by '*' in the input String before passing it to the ExpressionBuilder in the onEqual method (See the code below).
...
String txt = txtScreen.getText().toString();
// Replace special characters
txt = txt.replaceAll("x", "*").replaceAll("÷", "/");
// Create an Expression (A class from exp4j library)
Expression expression = new ExpressionBuilder(txt).build();
...

Hope I have answered your question, if please let me know.

Reply
avatar
darcoder
AUTHOR
July 31, 2016 at 2:23 PM delete

Hi. I don't quite understand the purpose of the stateError variable. Can you please explain? Thank you

Reply
avatar
Gobinath
AUTHOR
August 1, 2016 at 8:21 AM delete

Hi,
It is used as a flag to indicate that the last operation caused to an ArithmeticException and the display shows "ERROR" as the output. Later if the current state is error, a new input must replace the output "ERROR" message" If the current state is not an error state, the input will be appended to the existing expression. Similarly a dot cannot be placed after error state, equal operator cannot execute in an error state, etc.

Reply
avatar
Fajar Khan
AUTHOR
August 4, 2016 at 11:43 PM delete

Hello sir, the code works fine but i want add +/- and % button in my calculator, How can i add that? -/+ button simply change positive to negative or vice versa. i already created two button and set ID in XML file. i have no idea what i need to add on java file to add these buttons. Please help me,Thanks in advance!

Reply
avatar
Ishaant
AUTHOR
August 11, 2016 at 4:23 PM delete

Hey Sir i am very much new to android.. I choose your example for practice. but when i run the program i cant find any display.. Please help.. I can't find any solution yet.. Thanks

Reply
avatar
Gobinath
AUTHOR
August 11, 2016 at 7:46 PM delete

Hi,
Please share the Logcat error message in a new comment thread so that I can try my best to find out the problem.

Reply
avatar
avi D
AUTHOR
September 23, 2016 at 10:51 AM delete

These tutorials are good to get the basics done.. I was able to build my own Calculator..
Link : https://goo.gl/oqhLK2

Reply
avatar
Ali Ikram
AUTHOR
September 27, 2016 at 7:00 AM delete

Hi, My emulator is not displaying anything. There are no errors in the logcat neither in the code. The screenshot of the emulator is attached

Reply
avatar
Ali Ikram
AUTHOR
September 27, 2016 at 7:02 AM delete

https://uploads.disquscdn.com/images/a268f8f0b0682b91da1c9a49ddddc2ecc878746d6f2306e0ad9cf170518aa892.png

Hi my emulator is not displaying anything and there are no errors in the code or logcat. Please help

Reply
avatar
কিউরিয়াস বালক
AUTHOR
December 2, 2016 at 4:50 PM delete

HAving problem with the "R" help me

https://uploads.disquscdn.com/images/58dd715053f283a0ae8d91b7463d2cd34267e77a650e8e1271690046ae31b3ac.png

Reply
avatar
Gobinath
AUTHOR
December 5, 2016 at 5:08 AM delete

I think the problem is Android SDK. Could you install the Android SDK and add it to the project using the steps given in the screenshot console.

Reply
avatar
Vivek Kalola
AUTHOR
December 19, 2016 at 1:08 AM delete

Hello There I cant run the above mention package. Help me out please. I m getting this error while building the project.

Error:A problem occurred configuring project ':app'.
> Could not resolve all dependencies for configuration ':app:_debugApkCopy'.
> Could not resolve net.objecthunter:exp4j:0.3.2.
Required by:
Calculator_V1:app:unspecified
> Could not resolve net.objecthunter:exp4j:0.3.2.
> Could not get resource 'https://jcenter.bintray.com/net/objecthunter/exp4j/0.3.2/exp4j-0.3.2.pom'.
> Could not GET 'https://jcenter.bintray.com/net/objecthunter/exp4j/0.3.2/exp4j-0.3.2.pom'.
> repo.jfrog.org

Reply
avatar
Edward Kenway
AUTHOR
April 20, 2017 at 6:22 AM delete

Why can't the dots show at the first set of number(s) before the arithmetic signs e.g 5.2 + 2.31 the dot does not show in front of the 5 but shows in front of 2..

Reply
avatar
tahseen ullah
AUTHOR
May 25, 2017 at 1:23 AM delete

Tutorial is outstanding, But there is an issue, I divide 100/3 = 33.3333333333333 as shown in screenshot

https://uploads.disquscdn.com/images/e15269f0229c9faf30e95b946f36f5f1d12857d3e314183ccab79feef6644dc1.png

After this none button is work except Clear(C) and Delete(Del), how can i resolve it.

Reply
avatar
tahseen ullah
AUTHOR
May 25, 2017 at 9:58 AM delete

Sir, From which you belong?

Reply
avatar
tahseen ullah
AUTHOR
May 25, 2017 at 9:59 AM delete

Outstanding Tutorial....

Reply
avatar
shubh aora
AUTHOR
June 20, 2017 at 3:21 PM delete

sir i want to add more buttons like percentage and +/-. will you please tell me the code of both please sir

Reply
avatar
vishwanath appu
AUTHOR
September 26, 2017 at 3:47 PM delete

im geting the error like..... couldn't find compile() for arguments[dir:libs] on object of type org.gradle.api.internal.dsl.dependecies.defaultDependencyHandler.

also can't resolve symbol net.

Reply
avatar

Contact Form

Name

Email *

Message *