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


Comments
Post a Comment