Pertemuan 6 - Membuat Aplikasi Kalkulator

Nama: Kadek Fajar Pramartha Yasodana
NRP: 5025231185
Kelas: PPB (C)

Pertemuan 6: Membuat Aplikasi Kalkulator Sederhana

Didalam tugas ini, kita diminta untuk membuat sebuah kalkulator sederhana dengan tambahan user interface android yang dibuat dengan jetpack compose. Dalam pembuatan user interface calculator ini jika kita membayangkan diri seperti halnya membuat website dengan html/css, sebenarnya dalam pembuatan aplikasi android tidak jauh berbeda dengan pola pemikiran pembuatan yang sama dalam membuat section sectionnya. Perbedaannya hanya dalam syntaxnya saja, tetapi pemikirannya cukup mirip. Maka dari itu, disini saya akan menjelaskan dengan menggunakan bahasa mirip halnya membuat web.

package com.fajary.simplecalculator

import android.os.Bundle
import android.widget.Space
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
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.fillMaxHeight
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.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.fajary.simplecalculator.ui.theme.SimpleCalculatorTheme
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
SimpleCalculatorTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
CalculatorApp(
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}

@Composable
fun CalculatorApp(modifier: Modifier = Modifier) {
var firstInput by remember {
mutableStateOf("")
}
var secondInput by remember {
mutableStateOf(value = "")
}
var calculatorOperand by remember {
mutableStateOf(value = "+")
}
var calculationInfo by remember {
mutableStateOf(value = "")
}

Column(
modifier = modifier.
fillMaxSize()
.padding(
start = 24.dp,
end = 24.dp,
top = 32.dp,
bottom = 32.dp
),
) {
Text(
text = "Simple Calculator",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
fontSize = 24.sp
)

Spacer(modifier = Modifier.height(24.dp))

Text(
text = "First Input"
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = firstInput,
onValueChange = { firstInput = it },
modifier = Modifier.fillMaxWidth(),
textStyle = TextStyle(fontSize = 28.sp),
singleLine = true,
placeholder = { Text("0") }
)

Spacer(modifier = Modifier.height(16.dp))

Text(
text = "Second Input"
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = secondInput,
onValueChange = { secondInput = it },
modifier = Modifier.fillMaxWidth(),
textStyle = TextStyle(fontSize = 28.sp),
singleLine = true,
placeholder = { Text("0") }
)

Spacer(modifier = Modifier.height(16.dp))

Text(
text = "Operation"
)
Spacer(modifier = Modifier.height(8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(
onClick = {
calculatorOperand = "+"
},
colors = if(calculatorOperand == "+")
ButtonDefaults.buttonColors(
containerColor = Color.Blue
)
else
ButtonDefaults.buttonColors(
containerColor = Color.Gray
)
) {
Text("+")
}
Button(
onClick = {
calculatorOperand = "-"
},
colors = if(calculatorOperand == "-")
ButtonDefaults.buttonColors(
containerColor = Color.Blue
)
else
ButtonDefaults.buttonColors(
containerColor = Color.Gray
)
) {
Text("-")
}
Button(
onClick = {
calculatorOperand = "x"
},
colors = if(calculatorOperand == "x")
ButtonDefaults.buttonColors(
containerColor = Color.Blue
)
else
ButtonDefaults.buttonColors(
containerColor = Color.Gray
)
) {
Text("x")
}
Button(
onClick = {
calculatorOperand = "/"
},
colors = if(calculatorOperand == "/")
ButtonDefaults.buttonColors(
containerColor = Color.Blue
)
else
ButtonDefaults.buttonColors(
containerColor = Color.Gray
)
) {
Text("/")
}
Button(
onClick = {
calculatorOperand = "mod"
},
colors = if(calculatorOperand == "mod")
ButtonDefaults.buttonColors(
containerColor = Color.Blue
)
else
ButtonDefaults.buttonColors(
containerColor = Color.Gray
)
) {
Text("Mod")
}
}

Spacer(modifier = Modifier.weight(1f))

Text(
text = if(calculationInfo == "")
"No calculation have been operated"
else
calculationInfo,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
fontSize = 24.sp
)

Spacer(modifier = Modifier.weight(1f))

Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
Button(
onClick = {
val num1 = firstInput.toDoubleOrNull()
val num2 = secondInput.toDoubleOrNull()

if (num1 == null || num2 == null) {
calculationInfo = "Invalid input"
return@Button
}

val result = when (calculatorOperand) {
"+" -> num1 + num2
"-" -> num1 - num2
"x" -> num1 * num2
"/" -> if (num2 != 0.0) num1 / num2 else "Cannot divide by 0"
"mod" -> if (num2 != 0.0) num1 % num2 else "Cannot mod by 0"
else -> "Unknown operation"
}

calculationInfo = "$result"
}
) {
Text(
text = "Calculate"
)
}
}
}
}

@Preview(showBackground = true)
@Composable
fun CalculatorAppPreview() {
SimpleCalculatorTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
CalculatorApp(
modifier = Modifier.padding(innerPadding)
)
}
}
}

1. Fungsi MainActivity
Fungsi ini merupakan entry point dari aplikasi Android. Di dalam onCreate, aplikasi mengaktifkan mode edge-to-edge dan memanggil setContent untuk menampilkan UI berbasis Compose. SimpleCalculatorTheme berfungsi seperti global CSS/theme, sedangkan Scaffold bertindak seperti layout utama (mirip <body> di HTML) yang mengatur struktur dasar layar. Kemudian CalculatorApp dipanggil sebagai isi utama tampilan.

2. Fungsi CalculatorAppPreview
Fungsi ini digunakan untuk preview UI di Android Studio tanpa menjalankan aplikasi di device. Scaffold dan CalculatorApp dipanggil kembali untuk menampilkan tampilan yang sama seperti runtime.

3. Fungsi CalculatorApp (State Management)
Pada awal fungsi, terdapat beberapa state menggunakan remember dan mutableStateOf. Variabel seperti firstInput, secondInput, calculatorOperand, dan calculationInfo berfungsi sebagai penyimpan data yang akan otomatis memperbarui UI ketika nilainya berubah. Ini mirip seperti state pada JavaScript React, di mana perubahan state akan langsung merender ulang tampilan. Untuk tampilan yang dirender, bisa dilihat dalam beberapa bagian

Column (Layout Utama)
Column digunakan sebagai layout utama yang menyusun semua elemen secara vertikal (dari atas ke bawah). Properti fillMaxSize() membuat layout memenuhi seluruh layar (mirip width: 100%; height: 100% di CSS), sedangkan padding(...) memberikan jarak di setiap sisi (seperti padding di CSS). Secara konsep, Column ini mirip <div> dengan display: flex; flex-direction: column;

Judul (Text: "Simple Calculator")
Komponen Text ini menampilkan judul aplikasi. Modifier fillMaxWidth() membuat teks memenuhi lebar container (seperti width: 100%), dan textAlign = Center membuat teks berada di tengah (mirip text-align: center). Font diatur menjadi bold dan ukuran 24sp untuk menonjolkan judul.

Input Pertama
Bagian ini terdiri dari label (Text "First Input") dan OutlinedTextField. Field ini digunakan untuk menerima input angka pertama dari user. fillMaxWidth() membuat input melebar penuh seperti <input style="width:100%">, sedangkan textStyle memperbesar font agar terlihat seperti display kalkulator. Spacer digunakan untuk memberikan jarak antar elemen (mirip margin-bottom).

Input Kedua
Strukturnya sama seperti input pertama, namun digunakan untuk angka kedua. State secondInput akan menyimpan nilai yang dimasukkan user. Secara layout, ini identik dengan elemen form kedua dalam HTML.

Row Operasi (Operator Buttons)
Row digunakan untuk menyusun tombol operasi secara horizontal (mirip <div style="display:flex; flex-direction:row;">). Properti fillMaxWidth() membuat baris memenuhi layar, dan Arrangement.SpaceEvenly mendistribusikan tombol secara merata (seperti justify-content: space-evenly).

Setiap Button mewakili operasi (+, -, x, /, mod). Warna tombol berubah berdasarkan state calculatorOperand, sehingga tombol yang aktif akan berwarna biru, sedangkan yang lain abu-abu. Ini mirip dengan button aktif pada UI web (selected state).

Spacer dengan weight(1f)
Spacer(weight = 1f) digunakan untuk mengambil ruang kosong yang tersisa dan mendorong elemen berikutnya ke bawah. Ini mirip dengan margin-top: auto atau flex-grow: 1 di CSS, yang membuat elemen di bawahnya berada di bagian bawah layar

Text Hasil (calculationInfo)
Bagian ini menampilkan hasil perhitungan atau pesan default jika belum ada operasi. Dengan fillMaxWidth() dan textAlign = Center, teks ditampilkan di tengah layar. Font yang besar (24sp) membuat hasil terlihat jelas seperti display kalkulator.

Row Tombol Calculate
Row ini berisi tombol utama “Calculate” dan diposisikan di tengah secara horizontal menggunakan Arrangement.Center. Secara konsep, ini seperti <div style="display:flex; justify-content:center;">. Tombol ini akan menjalankan logika perhitungan ketika ditekan.

Logika onClick Button
Saat tombol ditekan, input dikonversi ke Double menggunakan toDoubleOrNull() untuk menghindari error jika input tidak valid. Jika input invalid, maka ditampilkan pesan error. Jika valid, operasi dihitung menggunakan when (mirip switch-case). Hasilnya kemudian disimpan ke calculationInfo sehingga langsung ditampilkan di UI. Penanganan khusus juga dilakukan untuk pembagian atau modulo dengan nol.














Comments

Popular posts from this blog

Pertemuan 1 KPPL - Software Engineer

Pertemuan 13 OOP - Abstraksi & Simulasi Fox & Rabit

Pertemuan 5 OOP - Membuat Music Organizer