Calculator App - Android Studio - Compose

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

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

MainActivity.kt

package com.technifysoft.myapplication

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.technifysoft.myapplication.ui.theme.MyApplicationTheme

class MainActivityCompose : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            CalculatorApp()
        }
    }
}

@Composable
fun CalculatorApp() {
    var currentExpression by remember { mutableStateOf("") }
    var result by remember { mutableStateOf("0") }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White)
            .padding(8.dp),
        verticalArrangement = Arrangement.SpaceBetween
    ) {
        // Solution Text
        Text(
            text = currentExpression,
            modifier = Modifier
                .fillMaxWidth()
                .weight(1f)
                .padding(16.dp),
            textAlign = TextAlign.End,
            fontSize = 18.sp,
            color = Color.Black
        )

        // Result Text
        Text(
            text = result,
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            textAlign = TextAlign.End,
            fontSize = 24.sp,
            color = Color.Black,
            fontWeight = FontWeight.Bold
        )

        // Buttons Layout
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color(0xFFF1F1F1))
                .padding(vertical = 8.dp, horizontal = 4.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val orange = Color(0xFFFF9800)
            val blue = Color(0xFF2196F3)
            val yellow = Color(0xFFFFC107)

            // Top row
            Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
                Spacer(modifier = Modifier.weight(0.67f))
                CalcButton("AC", yellow, Color(0xFFF44336)) {
                    currentExpression = ""
                    result = "0"
                }
                CalcButton("C", yellow, Color(0xFFF44336)) {
                    if (currentExpression.isNotEmpty())
                        currentExpression = currentExpression.dropLast(1)
                    result = getResult(currentExpression)
                }
            }

            val buttons = listOf(
                listOf("(", ")", "%", "/"),
                listOf("7", "8", "9", "*"),
                listOf("4", "5", "6", "+"),
                listOf("1", "2", "3", "-"),
                listOf("0", ".", "=")
            )

            buttons.forEach { row ->
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    row.forEach { label ->
                        val color =
                            when (label) {
                                "/", "*", "+", "-", "%", "=" -> orange
                                else -> blue
                            }
                        val weight = if (label == "0") 0.67f else 1f

                        CalcButton(label, color, Color.White, Modifier.weight(weight)) {
                            when (label) {
                                "=" -> {
                                    val res = getResult(currentExpression)
                                    if (res != "Err") {
                                        currentExpression = res
                                        result = res
                                    }
                                }

                                else -> {
                                    currentExpression = formatExpressionForDisplay(currentExpression + label)
                                    result = getResult(currentExpression)
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun CalcButton(
    label: String,
    background: Color,
    textColor: Color,
    modifier: Modifier = Modifier,
    onClick: () -> Unit
) {
    Button(
        onClick = onClick,
        modifier = modifier
            .padding(4.dp)
            .height(60.dp),
        colors = ButtonDefaults.buttonColors(containerColor = background),
        shape = RoundedCornerShape(16.dp)
    ) {
        Text(text = label, fontSize = 22.sp, fontWeight = FontWeight.Bold, color = textColor)
    }
}

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
}

// Expression evaluation helper (same logic)
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()
}


/**
 * GreetingPreview is a composable function for previewing the MainUI in Android Studio.
 * It is annotated with @Preview to enable live preview.
 *
 */
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme {
        CalculatorApp()
    }
}

🔍 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