Calculator App - Android Studio - Kotlin

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

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.


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.kt

package com.technifysoft.myapplication

import android.os.Bundle
import android.view.View
import android.widget.Button
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.technifysoft.myapplication.databinding.ActivityMainBinding

class MainActivityy : AppCompatActivity(), View.OnClickListener {

    private lateinit var binding: ActivityMainBinding
    private var currentExpression = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        val buttons = listOf(
            binding.button0, binding.button1, binding.button2, binding.button3, binding.button4,
            binding.button5, binding.button6, binding.button7, binding.button8, binding.button9,
            binding.buttonPlus, binding.buttonMinus, binding.buttonMultiply, binding.buttonDivide,
            binding.buttonDot, binding.buttonOpenBracket, binding.buttonCloseBracket,
            binding.buttonC, binding.buttonAc, binding.buttonEquals, binding.buttonModular
        )

        buttons.forEach { it.setOnClickListener(this) }
    }

    override fun onClick(v: View) {
        val button = v as Button
        val buttonText = button.text.toString()
        val viewId = v.id

        when (viewId) {
            binding.buttonEquals.id -> {
                val result = binding.resultTv.text.toString()
                if (result != "Err") {
                    currentExpression = result
                    binding.solutionTv.text = currentExpression
                }
                return
            }

            binding.buttonAc.id -> {
                currentExpression = ""
                binding.solutionTv.text = ""
                binding.resultTv.text = "0"
                return
            }

            binding.buttonC.id -> {
                if (currentExpression.isNotEmpty()) {
                    currentExpression = currentExpression.dropLast(1)
                }
            }

            else -> {
                currentExpression += buttonText
            }
        }

        val displayExpression = formatExpressionForDisplay(currentExpression)
        binding.solutionTv.text = displayExpression

        val finalResult = getResult(currentExpression)
        if (finalResult != "Err") {
            binding.resultTv.text = finalResult
        }
    }

    private fun formatExpressionForDisplay(expression: String): String {
        var formatted = expression
        formatted = formatted.replace(Regex("(?<=\\d)(?=\\()"), "*")  // 5( -> 5*(
        formatted = formatted.replace(Regex("(?<=\\))(?=\\d)"), "*")  // )5 -> )*5
        formatted = formatted.replace(Regex("(?<=\\))(?=\\()"), "*")  // )( -> )*(
        formatted = formatted.replace(Regex("(?<=%)(?=\\d|\\()"), "*") // 5%2 -> 5%*2 or 5%( -> 5%*(
        return formatted
    }

    private fun getResult(data: String): String {
        try {
            // Handle "100+10%" or "200-15%"
            val percentPattern = Regex("(.+)([+-])(\\d*\\.?\\d+)%")
            val match = percentPattern.matchEntire(data)
            if (match != null) {
                val (baseExpr, operator, percentValueStr) = match.destructured
                val baseResultStr = getResult(baseExpr)
                val baseValue = baseResultStr.toDouble()
                val percentValue = percentValueStr.toDouble()
                val percentOfBase = baseValue * (percentValue / 100.0)
                val finalResult =
                    if (operator == "+") baseValue + percentOfBase else baseValue - percentOfBase
                return finalResult.toString()
            }

            // Inline percentages (5% → 0.05)
            var parsedData = data.replace(Regex("(\\d*\\.?\\d+)%")) {
                val value = it.groupValues[1].toDouble()
                "(${value / 100.0})"
            }

            // Implicit multiplication
            parsedData = parsedData
                .replace(Regex("(?<=\\d)(?=\\()"), "*")
                .replace(Regex("(?<=\\))(?=\\d)"), "*")
                .replace(Regex("(?<=\\))(?=\\()"), "*")

            return eval(parsedData).toString()
        } catch (e: Exception) {
            return "Err"
        }
    }

    private fun eval(str: String): Double {
        return object {
            var pos = -1
            var ch = 0

            fun nextChar() {
                ch = if (++pos < str.length) str[pos].code else -1
            }

            fun eat(charToEat: Int): Boolean {
                while (ch == ' '.code) nextChar()
                return if (ch == charToEat) {
                    nextChar()
                    true
                } else false
            }

            fun parse(): Double {
                nextChar()
                val x = parseExpression()
                if (pos < str.length) throw RuntimeException("Unexpected: ${str[pos]}")
                return x
            }

            fun parseExpression(): Double {
                var x = parseTerm()
                while (true) {
                    x = when {
                        eat('+'.code) -> x + parseTerm()
                        eat('-'.code) -> x - parseTerm()
                        else -> return x
                    }
                }
            }

            fun parseTerm(): Double {
                var x = parseFactor()
                while (true) {
                    x = when {
                        eat('*'.code) -> x * parseFactor()
                        eat('/'.code) -> x / parseFactor()
                        else -> return x
                    }
                }
            }

            fun parseFactor(): Double {
                if (eat('+'.code)) return parseFactor()
                if (eat('-'.code)) return -parseFactor()

                val startPos = pos
                val x: Double = when {
                    eat('('.code) -> {
                        val result = parseExpression()
                        eat(')'.code)
                        result
                    }

                    (ch in '0'.code..'9'.code) || ch == '.'.code -> {
                        while ((ch in '0'.code..'9'.code) || ch == '.'.code) nextChar()
                        str.substring(startPos, pos).toDouble()
                    }

                    else -> throw RuntimeException("Unexpected: ${ch.toChar()}")
                }
                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