Calculator App - Android Studio - Java

How to develop a complete Calculator App using Android Studio and Java

I’ve created a modern calculator app using Android Studio (Java) with a clean and colorful interface. It supports all standard arithmetic operations, including addition, subtraction, multiplication, division, brackets, and percentages (%).

The app accurately handles expressions like:
25+(10/2)-5*(5%*2)+20+50% = 74.25

Designed with a responsive layout, bright orange and blue buttons, and smooth calculation handling — it’s perfect for anyone learning Android development or wanting to build a fully functional calculator UI from scratch.

>> Check for Kotlin        (Coming Soon)
>> Check for Compose   (Coming Soon)

Code

activity_main.xml

<?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">

    <TextView
        android:id="@+id/solution_tv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        android:layout_weight="1"
        android:textAlignment="textEnd"
        android:textColor="@color/black"
        android:textSize="18sp"
        tools:text="25+(10/2)-5*(5%*2)+20+50%" />

    <TextView
        android:id="@+id/result_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="0"
        android:textAlignment="textEnd"
        android:textColor="@color/black"
        android:textSize="24sp"
        tools:text="=74.25" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#F1F1F1"
        android:orientation="vertical"
        android:paddingHorizontal="4dp"
        android:paddingVertical="8dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="end"
            android:orientation="horizontal">

            <Space
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="0.67" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_ac"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FFC107"
                android:minHeight="60dp"
                android:text="AC"
                android:textColor="#F44336"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_c"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FFC107"
                android:minHeight="60dp"
                android:text="C"
                android:textColor="#F44336"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_open_bracket"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FF9800"
                android:minHeight="60dp"
                android:text="("
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_close_bracket"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FF9800"
                android:minHeight="60dp"
                android:text=")"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_modular"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FF9800"
                android:minHeight="60dp"
                android:text="%"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_divide"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FF9800"
                android:minHeight="60dp"
                android:text="/"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_7"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="7"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_8"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="8"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_9"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="9"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_multiply"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FF9800"
                android:minHeight="60dp"
                android:text="*"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_4"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="4"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_5"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="5"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_6"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="6"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_plus"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FF9800"
                android:minHeight="60dp"
                android:text="+"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="1"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="2"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="3"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_minus"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FF9800"
                android:minHeight="60dp"
                android:text="-"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_0"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight=".67"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="0"
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_dot"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#2196F3"
                android:minHeight="60dp"
                android:text="."
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/button_equals"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_weight="1"
                android:backgroundTint="#FF9800"
                android:minHeight="60dp"
                android:text="="
                android:textColor="@color/white"
                android:textSize="22sp"
                android:textStyle="bold"
                app:cornerRadius="16dp" />

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

MainActivity.java

package com.technifysoft.myapplication;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.technifysoft.myapplication.databinding.ActivityMainBinding;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ActivityMainBinding binding;
    private String currentExpression = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        ViewCompat.setOnApplyWindowInsetsListener(binding.getRoot(), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        binding.button0.setOnClickListener(this);
        binding.button1.setOnClickListener(this);
        binding.button2.setOnClickListener(this);
        binding.button3.setOnClickListener(this);
        binding.button4.setOnClickListener(this);
        binding.button5.setOnClickListener(this);
        binding.button6.setOnClickListener(this);
        binding.button7.setOnClickListener(this);
        binding.button8.setOnClickListener(this);
        binding.button9.setOnClickListener(this);
        binding.buttonPlus.setOnClickListener(this);
        binding.buttonMinus.setOnClickListener(this);
        binding.buttonMultiply.setOnClickListener(this);
        binding.buttonDivide.setOnClickListener(this);
        binding.buttonDot.setOnClickListener(this);
        binding.buttonOpenBracket.setOnClickListener(this);
        binding.buttonCloseBracket.setOnClickListener(this);
        binding.buttonC.setOnClickListener(this);
        binding.buttonAc.setOnClickListener(this);
        binding.buttonEquals.setOnClickListener(this);
        binding.buttonModular.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Button button = (Button) v;
        String buttonText = button.getText().toString();
        int viewId = v.getId();

        if (viewId == binding.buttonEquals.getId()) {
            String result = binding.resultTv.getText().toString();
            if (!result.equals("Err")) {
                currentExpression = result;
                binding.solutionTv.setText(currentExpression);
            }
            return;
        } else if (viewId == binding.buttonAc.getId()) {
            currentExpression = "";
            binding.solutionTv.setText("");
            binding.resultTv.setText("0");
            return;
        } else if (viewId == binding.buttonC.getId()) {
            if (!currentExpression.isEmpty()) {
                currentExpression = currentExpression.substring(0, currentExpression.length() - 1);
            }
        } else {
            currentExpression = currentExpression + buttonText;
        }

        String displayExpression = formatExpressionForDisplay(currentExpression);
        binding.solutionTv.setText(displayExpression);

        String finalResult = getResult(currentExpression);

        if (!finalResult.equals("Err")) {
            binding.resultTv.setText(finalResult);
        }
    }

    private String formatExpressionForDisplay(String expression) {
        // Add '*' for implicit multiplication for display purposes
        expression = expression.replaceAll("(?<=\\d)(?=\\()", "*"); // e.g., 5( -> 5*(
        expression = expression.replaceAll("(?<=\\))(?=\\d)", "*"); // e.g., )5 -> )*5
        expression = expression.replaceAll("(?<=\\))(?=\\()", "*"); // e.g., )( -> )*(
        // Also handle percentage cases for display
        expression = expression.replaceAll("(?<=%)(?=\\d|\\()", "*"); // e.g., 5%2 -> 5%*2 or 5%( -> 5%*(
        return expression;
    }


    String getResult(String data) {
        try {
            // Handle expressions ending in +N% or -N% (e.g., "100+10%")
            Pattern endWithPercentPattern = Pattern.compile("(.+)([+-])(\\d*\\.?\\d+)%");
            Matcher endWithPercentMatcher = endWithPercentPattern.matcher(data);

            if (endWithPercentMatcher.matches()) {
                String baseExpr = endWithPercentMatcher.group(1);
                String operator = endWithPercentMatcher.group(2);
                double percentValue = Double.parseDouble(endWithPercentMatcher.group(3));

                // Recursively evaluate the base expression
                String baseResultStr = getResult(baseExpr);
                double baseValue = Double.parseDouble(baseResultStr);

                double percentOfBase = baseValue * (percentValue / 100.0);

                double finalResult;
                if (operator.equals("+")) {
                    finalResult = baseValue + percentOfBase;
                } else { // operator is "-"
                    finalResult = baseValue - percentOfBase;
                }
                return String.valueOf(finalResult);
            }

            // Handle inline percentages (e.g., "5%2" or "(5%)")
            Pattern inlinePercentPattern = Pattern.compile("(\\d*\\.?\\d+)%");
            Matcher inlinePercentMatcher = inlinePercentPattern.matcher(data);
            StringBuffer sb = new StringBuffer();
            while (inlinePercentMatcher.find()) {
                double value = Double.parseDouble(inlinePercentMatcher.group(1));
                inlinePercentMatcher.appendReplacement(sb, "(" + (value / 100.0) + ")");
            }
            inlinePercentMatcher.appendTail(sb);
            data = sb.toString();

            // Handles implicit multiplication (e.g., "2(3)" or "(2)(3)")
            data = data.replaceAll("(?<=\\d)(?=\\()", "*");
            data = data.replaceAll("(?<=\\))(?=\\d)", "*");
            data = data.replaceAll("(?<=\\))(?=\\()", "*");

            return String.valueOf(eval(data));
        } catch (Exception e) {
            return "Err";
        }
    }

    public static double eval(final String str) {
        return new Object() {
            int pos = -1, ch;

            void nextChar() {
                ch = (++pos < str.length()) ? str.charAt(pos) : -1;
            }

            boolean eat(int charToEat) {
                while (ch == ' ') nextChar();
                if (ch == charToEat) {
                    nextChar();
                    return true;
                }
                return false;
            }

            double parse() {
                nextChar();
                double x = parseExpression();
                if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char) ch);
                return x;
            }

            double parseExpression() {
                double x = parseTerm();
                for (; ; ) {
                    if (eat('+')) x += parseTerm();
                    else if (eat('-')) x -= parseTerm();
                    else return x;
                }
            }

            double parseTerm() {
                double x = parseFactor();
                for (; ; ) {
                    if (eat('*')) x *= parseFactor();
                    else if (eat('/')) x /= parseFactor();
                    else return x;
                }
            }

            double parseFactor() {
                if (eat('+')) return parseFactor();
                if (eat('-')) return -parseFactor();

                double x;
                int startPos = this.pos;
                if (eat('(')) {
                    x = parseExpression();
                    eat(')');
                } else if ((ch >= '0' && ch <= '9') || ch == '.') {
                    while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
                    x = Double.parseDouble(str.substring(startPos, this.pos));
                } else {
                    throw new RuntimeException("Unexpected: " + (char) ch);
                }

                return x;
            }
        }.parse();
    }
} 

🔍 Related Searches

  • Calculator app android studio source code 
  • Simple calculator app android studio java 
  • Calculator app using java in android studio 
  • Android calculator project with source code 
  • How to make a calculator app in android studio 
  • Calculator app UI design android studio 
  • Android calculator tutorial for beginners 
  • Percentage calculator android app 
  • Calculator app using kotlin or java 
  • Beautiful calculator UI android studio 
  • Step by step calculator app android studio 
  • Android studio calculator XML layout 
  • Custom calculator buttons in android studio 
  • Arithmetic expression evaluator android java

📱 Screenshots
Calculator App - Android Studio - Java

Calculator App - Android Studio - Java


Comments

Popular posts from this blog

Picture In Picture | Android Studio | Kotlin

Manage External Storage Permission - Android Studio - Kotlin

How to add AIDL folder | Android Studio