-
-
Save parishsu/f4f0ceb1c9a80eadba58adc34361f71c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.multimodal | |
import android.util.Log | |
import androidx.compose.foundation.background | |
import androidx.compose.foundation.border | |
import androidx.compose.foundation.clickable | |
import androidx.compose.foundation.layout.Arrangement | |
import androidx.compose.foundation.layout.Box | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.Row | |
import androidx.compose.foundation.layout.Spacer | |
import androidx.compose.foundation.layout.fillMaxSize | |
import androidx.compose.foundation.layout.fillMaxWidth | |
import androidx.compose.foundation.layout.height | |
import androidx.compose.foundation.layout.padding | |
import androidx.compose.foundation.layout.size | |
import androidx.compose.foundation.shape.CircleShape | |
import androidx.compose.material.icons.Icons | |
import androidx.compose.material.icons.filled.Backspace | |
import androidx.compose.material.icons.filled.MoreVert | |
import androidx.compose.material3.Divider | |
import androidx.compose.material3.ExperimentalMaterial3Api | |
import androidx.compose.material3.Icon | |
import androidx.compose.material3.IconButton | |
import androidx.compose.material3.MaterialTheme | |
import androidx.compose.material3.Scaffold | |
import androidx.compose.material3.Surface | |
import androidx.compose.material3.Text | |
import androidx.compose.material3.TopAppBar | |
import androidx.compose.material3.TopAppBarDefaults | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.mutableStateOf | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.setValue | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.draw.clip | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.graphics.vector.ImageVector | |
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 java.text.DecimalFormat | |
/** | |
* Composable function to create a calculator screen. | |
* | |
* This screen displays a basic calculator layout with number buttons, | |
* operation buttons, and a display area. | |
*/ | |
@OptIn(ExperimentalMaterial3Api::class) | |
@Composable | |
fun CalculatorScreen() { | |
var displayValue by remember { mutableStateOf("") } // Current value displayed | |
var displayOperation by remember { mutableStateOf("") } // Current operation displayed | |
var previousValue by remember { mutableStateOf("") } // Previous value displayed | |
var lastOperation by remember { mutableStateOf("") } | |
Scaffold( | |
// Top app bar | |
topBar = { | |
TopAppBar( | |
title = { | |
Text( | |
text = "DEG", | |
style = MaterialTheme.typography.titleMedium, | |
fontWeight = FontWeight.Bold, | |
color = MaterialTheme.colorScheme.primary | |
) | |
}, | |
actions = { | |
IconButton(onClick = { /*TODO: Open more menu*/ }) { | |
Icon( | |
imageVector = Icons.Filled.MoreVert, | |
contentDescription = "More menu", | |
tint = MaterialTheme.colorScheme.primary | |
) | |
} | |
}, | |
colors = TopAppBarDefaults.topAppBarColors( | |
containerColor = MaterialTheme.colorScheme.surface, | |
) | |
) | |
}, | |
modifier = Modifier.fillMaxSize() | |
) { innerPadding -> | |
Surface( | |
modifier = Modifier | |
.fillMaxSize() | |
.padding(innerPadding) | |
.background(MaterialTheme.colorScheme.surface) | |
) { | |
Column( | |
modifier = Modifier | |
.fillMaxSize() | |
.padding(16.dp), | |
horizontalAlignment = Alignment.End | |
) { | |
// Display area for results | |
Box( | |
modifier = Modifier | |
.fillMaxWidth() | |
.height(80.dp) | |
.padding(16.dp), | |
contentAlignment = Alignment.BottomEnd | |
) { | |
Text( | |
text = displayValue.ifEmpty { "0" }, | |
fontSize = 48.sp, | |
color = MaterialTheme.colorScheme.onSurface, | |
textAlign = TextAlign.End, | |
) | |
} | |
Box( | |
modifier = Modifier | |
.fillMaxWidth() | |
.height(60.dp) | |
.padding(16.dp), | |
contentAlignment = Alignment.BottomEnd | |
) { | |
Text( | |
text = displayOperation, | |
fontSize = 24.sp, | |
color = MaterialTheme.colorScheme.secondary, | |
textAlign = TextAlign.End, | |
) | |
} | |
Divider( | |
modifier = Modifier.fillMaxWidth(), | |
color = MaterialTheme.colorScheme.outline | |
) | |
Spacer(modifier = Modifier.height(16.dp)) | |
// Calculator buttons | |
Column( | |
modifier = Modifier.fillMaxWidth(), | |
horizontalAlignment = Alignment.CenterHorizontally, | |
verticalArrangement = Arrangement.spacedBy(12.dp) | |
) { | |
// Row 1 | |
Row( | |
modifier = Modifier.fillMaxWidth(), | |
horizontalArrangement = Arrangement.spacedBy(12.dp) | |
) { | |
CalculatorButton( | |
text = "AC", | |
buttonColor = MaterialTheme.colorScheme.surfaceVariant | |
) { | |
displayValue = "" | |
displayOperation = "" | |
previousValue = "" | |
lastOperation = "" | |
} | |
CalculatorButton( | |
text = "+/-", | |
buttonColor = MaterialTheme.colorScheme.surfaceVariant | |
) { | |
if (displayValue.isNotEmpty()) { | |
displayValue = if (displayValue.startsWith("-")) { | |
displayValue.removePrefix("-") | |
} else { | |
"-$displayValue" | |
} | |
} | |
} | |
CalculatorButton( | |
text = "%", | |
buttonColor = MaterialTheme.colorScheme.surfaceVariant | |
) { | |
if (displayValue.isNotEmpty()) { | |
previousValue = displayValue | |
displayValue = "" | |
lastOperation = "%" | |
displayOperation = "$previousValue %" | |
} | |
} | |
CalculatorButton( | |
text = "÷", | |
buttonColor = MaterialTheme.colorScheme.primaryContainer, | |
textColor = MaterialTheme.colorScheme.onPrimaryContainer | |
) { | |
if (displayValue.isNotEmpty()) { | |
previousValue = displayValue | |
displayValue = "" | |
lastOperation = "÷" | |
displayOperation = "$previousValue ÷" | |
} | |
} | |
} | |
// Row 2 | |
Row( | |
modifier = Modifier.fillMaxWidth(), | |
horizontalArrangement = Arrangement.spacedBy(12.dp) | |
) { | |
CalculatorButton(text = "7") { | |
updateDisplayValue( | |
"7", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton(text = "8") { | |
updateDisplayValue( | |
"8", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton(text = "9") { | |
updateDisplayValue( | |
"9", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton( | |
text = "x", | |
buttonColor = MaterialTheme.colorScheme.primaryContainer, | |
textColor = MaterialTheme.colorScheme.onPrimaryContainer | |
) { | |
if (displayValue.isNotEmpty()) { | |
previousValue = displayValue | |
displayValue = "" | |
lastOperation = "x" | |
displayOperation = "$previousValue x" | |
} | |
} | |
} | |
// Row 3 | |
Row( | |
modifier = Modifier.fillMaxWidth(), | |
horizontalArrangement = Arrangement.spacedBy(12.dp) | |
) { | |
CalculatorButton(text = "4") { | |
updateDisplayValue( | |
"4", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton(text = "5") { | |
updateDisplayValue( | |
"5", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton(text = "6") { | |
updateDisplayValue( | |
"6", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton( | |
text = "-", | |
buttonColor = MaterialTheme.colorScheme.primaryContainer, | |
textColor = MaterialTheme.colorScheme.onPrimaryContainer | |
) { | |
if (displayValue.isNotEmpty()) { | |
previousValue = displayValue | |
displayValue = "" | |
lastOperation = "-" | |
displayOperation = "$previousValue -" | |
} | |
} | |
} | |
// Row 4 | |
Row( | |
modifier = Modifier.fillMaxWidth(), | |
horizontalArrangement = Arrangement.spacedBy(12.dp) | |
) { | |
CalculatorButton(text = "1") { | |
updateDisplayValue( | |
"1", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton(text = "2") { | |
updateDisplayValue( | |
"2", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton(text = "3") { | |
updateDisplayValue( | |
"3", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton( | |
text = "+", | |
buttonColor = MaterialTheme.colorScheme.primaryContainer, | |
textColor = MaterialTheme.colorScheme.onPrimaryContainer | |
) { | |
if (displayValue.isNotEmpty()) { | |
previousValue = displayValue | |
displayValue = "" | |
lastOperation = "+" | |
displayOperation = "$previousValue +" | |
} | |
} | |
} | |
// Row 5 | |
Row( | |
modifier = Modifier.fillMaxWidth(), | |
horizontalArrangement = Arrangement.spacedBy(12.dp) | |
) { | |
CalculatorButton(text = "0") { | |
updateDisplayValue( | |
"0", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton(text = ".") { | |
updateDisplayValue( | |
".", | |
displayValue, | |
setDisplayValue = { displayValue = it }) | |
} | |
CalculatorButton( | |
icon = Icons.Filled.Backspace, | |
iconDescription = "backspace", | |
buttonColor = MaterialTheme.colorScheme.surfaceVariant | |
) { | |
if (displayValue.isNotEmpty()) { | |
displayValue = displayValue.dropLast(1) | |
} | |
} | |
CalculatorButton( | |
text = "=", | |
buttonColor = MaterialTheme.colorScheme.tertiary, | |
textColor = MaterialTheme.colorScheme.onTertiary | |
) { | |
if (displayValue.isNotEmpty() && previousValue.isNotEmpty()) { | |
displayValue = calculateResult( | |
previousValue, | |
displayValue, | |
lastOperation | |
).toString() | |
} | |
displayOperation = "" | |
lastOperation = "" | |
previousValue = "" | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Composable function to create a calculator button. | |
* | |
* This function creates a circular button with a text or icon. | |
* | |
* @param text The text to display on the button (optional). | |
* @param icon The icon to display on the button (optional). | |
* @param iconDescription The description for the icon (optional). | |
* @param onClick Callback function to be executed when the button is clicked. | |
*/ | |
@Composable | |
fun CalculatorButton( | |
text: String? = null, | |
icon: ImageVector? = null, | |
iconDescription: String? = null, | |
textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, | |
buttonColor: Color = MaterialTheme.colorScheme.surfaceVariant, | |
onClick: () -> Unit | |
) { | |
Box( | |
modifier = Modifier | |
.size(80.dp) | |
.clip(CircleShape) | |
.background(buttonColor) | |
.border(1.dp, MaterialTheme.colorScheme.outline, CircleShape) | |
.clickable { onClick() }, | |
contentAlignment = Alignment.Center | |
) { | |
if (text != null) { | |
Text( | |
text = text, | |
fontSize = 24.sp, | |
color = textColor, | |
fontWeight = FontWeight.Bold | |
) | |
} else if (icon != null) { | |
Icon( | |
imageVector = icon, | |
contentDescription = iconDescription, | |
tint = textColor, | |
modifier = Modifier.size(32.dp) | |
) | |
} | |
} | |
} | |
/** | |
* Function to update the display value. | |
* | |
* @param newValue The new value to append to the display. | |
*/ | |
fun updateDisplayValue(newValue: String, displayValue: String, setDisplayValue: (String) -> Unit) { | |
// Check if the value is "." and if already exists in the number | |
if (newValue == "." && displayValue.contains(".")) { | |
return | |
} | |
setDisplayValue(displayValue + newValue) | |
} | |
fun calculateResult(previousValue: String, displayValue: String, lastOperation: String): Double { | |
val num1 = previousValue.toDoubleOrNull() ?: 0.0 | |
val num2 = displayValue.toDoubleOrNull() ?: 0.0 | |
val decimalFormat = DecimalFormat("#.#######") | |
return when (lastOperation) { | |
"+" -> decimalFormat.format(num1 + num2).toDouble() | |
"-" -> decimalFormat.format(num1 - num2).toDouble() | |
"x" -> decimalFormat.format(num1 * num2).toDouble() | |
"÷" -> { | |
if (num2 == 0.0) { | |
Log.e("Calculator", "Error: Division by zero") | |
0.0 | |
} else { | |
decimalFormat.format(num1 / num2).toDouble() | |
} | |
} | |
"%" -> decimalFormat.format(num1 % num2).toDouble() | |
else -> 0.0 | |
} | |
} | |
/** | |
* Preview function to display CalculatorScreen in the IDE. | |
*/ | |
@Preview(showBackground = true) | |
@Composable | |
fun CalculatorScreenPreview() { | |
MaterialTheme { | |
CalculatorScreen() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment