┌──(rfi88㉿github)-[~]
└─$ cat ~/blog/2026-05-12-tutorial-source-code-bikin-kalkulator-android-mirip-iphone-pake-kotlin-xml-copy-paste-langsung-jadi.md

[TUTORIAL + SOURCE CODE] Bikin Kalkulator Android Mirip iPhone Pake Kotlin XML | Copy-Paste Langsung Jadi

12 May 2026 | [ cd ~/ ] | [ github ]

Banyak yang minta kode lengkapnya. Nih gue taro semua, tinggal copy-paste 100% work. Udah dites di Android Studio Narwhal 2026.1.1

Hasilnya:

Step 1: Setup Project

  1. Bikin project Empty Views Activity
  2. Hapus folder ui.theme
  3. build.gradle.kts (Project) hapus baris compose biar jadi gini:
build.gradle.kts (Project)
plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.kotlin.android) apply false
}
  1. build.gradle.kts (Module :app) tambahin library exp4j di dependencies:
build.gradle.kts (Module :app)
dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.appcompat)
    implementation(libs.material)
    implementation(libs.androidx.activity)
    implementation(libs.androidx.constraintlayout)
    
    // Ini buat ngitung
    implementation("net.objecthunter:exp4j:0.4.8")
    
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
}

Sync Now.


Step 2: KODE XML LENGKAP

Buka res/layout/activity_main.xml hapus semua, paste ini:

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000"
    android:padding="16dp">

    <TextView
        android:id="@+id/tvExpression"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:textColor="#808080"
        android:textSize="32sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tvResult"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:gravity="end"
        android:text="0"
        android:textColor="#FFFFFF"
        android:textSize="64sp"
        app:layout_constraintBottom_toTopOf="@+id/gridLayout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <GridLayout
        android:id="@+id/gridLayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:columnCount="4"
        android:rowCount="5"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <Button
            android:id="@+id/btnClear"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#FF9500"
            android:text="C"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btnDelete"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#FF9500"
            android:text="⌫"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btnPercent"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#FF9500"
            android:text="%"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btnDivide"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#FF9500"
            android:text="÷"
            android:textColor="#FFFFFF"
            android:textSize="32sp" />

        <Button
            android:id="@+id/btn7"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="7"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btn8"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="8"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btn9"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="9"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btnMultiply"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#FF9500"
            android:text="×"
            android:textColor="#FFFFFF"
            android:textSize="32sp" />

        <Button
            android:id="@+id/btn4"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="4"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btn5"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="5"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btn6"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="6"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btnMinus"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#FF9500"
            android:text="-"
            android:textColor="#FFFFFF"
            android:textSize="32sp" />

        <Button
            android:id="@+id/btn1"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="1"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btn2"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="2"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btn3"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="3"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btnPlus"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#FF9500"
            android:text="+"
            android:textColor="#FFFFFF"
            android:textSize="32sp" />

        <Button
            android:id="@+id/btn00"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="00"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btn0"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text="0"
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btnComma"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#333333"
            android:text=","
            android:textColor="#FFFFFF"
            android:textSize="28sp" />

        <Button
            android:id="@+id/btnEquals"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:layout_columnWeight="1"
            android:layout_margin="4dp"
            android:backgroundTint="#FF9500"
            android:text="="
            android:textColor="#FFFFFF"
            android:textSize="32sp" />

    </GridLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Step 3: KODE KOTLIN LENGKAP - FIXED

Buka MainActivity.kt hapus semua, paste ini. Ganti com.namakamu.calculator sama package name lu:

MainActivity.kt
package com.namakamu.calculator

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import net.objecthunter.exp4j.ExpressionBuilder

class MainActivity : AppCompatActivity() {

    private lateinit var tvExpression: TextView
    private lateinit var tvResult: TextView
    private var lastNumeric = false
    private var lastDot = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        tvExpression = findViewById(R.id.tvExpression)
        tvResult = findViewById(R.id.tvResult)

        // Angka
        setNumber(R.id.btn0, "0")
        setNumber(R.id.btn1, "1")
        setNumber(R.id.btn2, "2")
        setNumber(R.id.btn3, "3")
        setNumber(R.id.btn4, "4")
        setNumber(R.id.btn5, "5")
        setNumber(R.id.btn6, "6")
        setNumber(R.id.btn7, "7")
        setNumber(R.id.btn8, "8")
        setNumber(R.id.btn9, "9")
        setNumber(R.id.btn00, "00")

        // Operator
        setOperator(R.id.btnPlus, "+")
        setOperator(R.id.btnMinus, "-")
        setOperator(R.id.btnMultiply, "*")
        setOperator(R.id.btnDivide, "/")
        setOperator(R.id.btnPercent, "%")

        // Koma
        findViewById<Button>(R.id.btnComma).setOnClickListener {
            if (lastNumeric && !lastDot) {
                tvExpression.append(".")
                lastNumeric = false
                lastDot = true
            }
        }

        // Clear
        findViewById<Button>(R.id.btnClear).setOnClickListener {
            tvExpression.text = ""
            tvResult.text = "0"
            lastNumeric = false
            lastDot = false
        }

        // Hapus 1 karakter
        findViewById<Button>(R.id.btnDelete).setOnClickListener {
            val text = tvExpression.text.toString()
            if (text.isNotEmpty()) {
                tvExpression.text = text.dropLast(1)
            }
            try {
                val lastChar = tvExpression.text.toString().last()
                lastNumeric = lastChar.isDigit()
                lastDot = lastChar == '.'
            } catch (e: Exception) {
                lastNumeric = false
                lastDot = false
                tvResult.text = "0"
            }
        }

        // Sama dengan - FIXED × ÷
        findViewById<Button>(R.id.btnEquals).setOnClickListener {
            if (lastNumeric) {
                var txt = tvExpression.text.toString()
                   .replace("×", "*")
                   .replace("÷", "/")
                try {
                    val expression = ExpressionBuilder(txt).build()
                    val result = expression.evaluate()
                    val longResult = result.toLong()
                    tvResult.text = if (result == longResult.toDouble()) longResult.toString() else result.toString()
                } catch (e: Exception) {
                    tvResult.text = "Error"
                }
            }
        }
    }

    private fun setNumber(id: Int, number: String) {
        findViewById<Button>(id).setOnClickListener {
            tvExpression.append(number)
            lastNumeric = true
        }
    }

    private fun setOperator(id: Int, operator: String) {
        findViewById<Button>(id).setOnClickListener {
            if (lastNumeric && !isOperatorAdded(tvExpression.text.toString())) {
                tvExpression.append(operator)
                lastNumeric = false
                lastDot = false
            }
        }
    }

    private fun isOperatorAdded(value: String): Boolean {
        if (value.isEmpty()) return false
        val lastChar = value.last().toString()
        return lastChar == "+" || lastChar == "-" || lastChar == "*" || lastChar == "/" || lastChar == "%"
    }
}

Step 4: Run!

Pencet Shift + F10 atau tombol Run ijo. Jadi!

Test Case:

7 + 8 = 15
2 + 3 × 4 = 14
100 ÷ 4 % = 25

Error Yang Sering Muncul:

1. Merah semua di MainActivity
-> Belum Sync Project. Pencet File > Sync Project with Gradle Files

2. Unresolved reference: compose
-> Hapus folder ui.theme di dalem com.namakamu.calculator

3. App force close pas pencet =
-> Lupa tambahin implementation("net.objecthunter:exp4j:0.4.8")

Udah, itu doang. Kalau ada yang error komen aja. Kalo berhasil SS di komen yak!

Download Project Lengkap: Google Drive

#androidstudio #kotlin #tutorial #kalkulator #gratis #opensource


[+] Komentar

┌──(rfi88㉿github)-[~]
└─$ tail -f /dev/comments


┌──(rfi88㉿github)-[~]
└─$ exit

[✓] Connection closed.