revisi terbaru

This commit is contained in:
RafiFattan23 2025-11-07 12:59:51 +07:00
parent 0358bf15e4
commit 253cc3a6bb
8 changed files with 131 additions and 92 deletions

View File

@ -2,67 +2,61 @@
**Dibuat oleh:**
👨‍💻 **Rafi Fattan Fitriardi**
🆔 **NPM: 202310715002**
🏫 **Pemrograman Perangkat Bergerak - F5A5**
🆔 **NPM:** 202310715002
🏫 **Kelas:** Pemrograman Perangkat Bergerak - F5A5
---
## 📖 Deskripsi Aplikasi
Aplikasi **Kalkulator BMI (Body Mass Index)** ini dibuat sebagai proyek akhir mata kuliah **Pemrograman Perangkat Bergerak**.
Tujuan utama aplikasi ini adalah membantu pengguna menghitung **Indeks Massa Tubuh (BMI)** berdasarkan **berat badan (kg)** dan **tinggi badan (cm)** untuk mengetahui apakah berat badan tergolong **kurang, ideal, berlebih, atau obesitas**.
Tujuannya adalah membantu pengguna menghitung **Indeks Massa Tubuh (BMI)** berdasarkan **berat badan (kg/lbs)** dan **tinggi badan (cm/inci)** agar dapat mengetahui apakah berat badan tergolong **kurang, ideal, berlebih, atau obesitas**.
Aplikasi ini memiliki **dua halaman utama**:
1. **Halaman Biodata Pengembang** menampilkan informasi pembuat aplikasi (nama, NIM, kelas, dan foto), serta tombol **“MULAI”** untuk berpindah ke laman utama.
2. **Halaman Utama (Kalkulator BMI)** tempat pengguna menginput berat dan tinggi badan, menekan tombol **“Hitung BMI”**, lalu melihat hasil nilai BMI beserta kategori dan saran kesehatannya.
Aplikasi memiliki **dua halaman utama**:
1. 🧑‍💻 **Halaman Biodata Pengembang**
Menampilkan informasi pengembang (nama, NIM, kelas, dan foto), serta tombol **“MULAI”** untuk berpindah ke halaman utama.
2. ⚖️ **Halaman Utama (Kalkulator BMI)**
Pengguna dapat menginput berat dan tinggi badan, menekan tombol **“Hitung BMI”**, dan melihat hasil nilai BMI beserta **kategori serta saran kesehatannya**.
---
## ⚙️ Fitur Utama
- Input berat dan tinggi badan secara interaktif (bisa satuan SI atau USC).
- Perhitungan otomatis nilai BMI.
- Tampilan kategori hasil (Kurus, Normal, Gemuk, Obesitas).
- Antarmuka sederhana dan responsif.
- Navigasi antarhalaman menggunakan tombol **MULAI** dari halaman biodata.
- ✏️ Input berat dan tinggi badan secara interaktif (bisa satuan **SI** atau **USC**).
- 🧮 Perhitungan otomatis nilai BMI dengan opsi pembulatan hasil.
- 📊 Tampilan kategori hasil (Kurus, Normal, Gemuk, Obesitas).
- 🎨 Antarmuka sederhana, bersih, dan responsif menggunakan **Jetpack Compose**.
- 🔄 Navigasi antarhalaman dengan tombol **MULAI** dari halaman biodata.
---
## 🧩 Teknologi yang Digunakan
- **Android Studio (Kotlin)**
- **XML Layouts** untuk desain antarmuka
- **Intent** untuk navigasi antar activity
- **Drawable XML** untuk gradasi dan tema warna aplikasi
---
## 💡 Struktur Proyek
```
app/
├── java/com/example/bmiapp/
│ ├── SplashActivity.kt // Halaman biodata pengembang
│ ├── MainActivity.kt // Halaman utama kalkulator BMI
├── res/
│ ├── layout/
│ │ ├── activity_splash.xml
│ │ ├── activity_main.xml
│ ├── drawable/
│ │ ├── splash_gradient.xml
│ ├── mipmap/
│ │ ├── ic_launcher.png // Ikon aplikasi
│ │ ├── ic_launcher_round.png
│ ├── values/
│ ├── colors.xml
│ ├── strings.xml
│ ├── themes.xml
└── AndroidManifest.xml
```
- 💻 **Android Studio (Kotlin)**
- 🧱 **Jetpack Compose** & **XML Layouts** untuk desain antarmuka
- 🔗 **Intent** untuk navigasi antar activity
- 🎨 **Drawable XML & colors.xml** untuk tema warna dan efek gradasi
- 🧪 **Unit Test (disarankan)** untuk menguji akurasi perhitungan BMI
---
## 🧠 Kontribusi & Kredit
Aplikasi ini dikembangkan dengan bantuan **ChatGPT (OpenAI)** dalam pembuatan kode, desain antarmuka, dan penyusunan dokumentasi.
Semua logika, pengujian, dan penyempurnaan dilakukan secara mandiri oleh pengembang.
Aplikasi ini dikembangkan dengan bantuan **ChatGPT (OpenAI)** dalam pembuatan kode, desain antarmuka, dan dokumentasi.
Semua logika perhitungan, pengujian, dan penyempurnaan dilakukan mandiri oleh pengembang.
---
## 🕓 Change Log (Ringkas)
- ✅ **Migrasi kode dasar** dari kalkulator tip ke kalkulator BMI berbasis Kotlin Compose.
- ⚙️ **Penambahan mode satuan USC (Inci & Lbs)** dengan validasi tinggi minimal 4 inci.
- 🧮 **Perbaikan rumus perhitungan BMI** agar sesuai standar WHO.
- 🎨 **Desain ulang Splash Screen** dengan tombol “MULAI” berwarna hijau dan latar gradasi biru-hijau.
- 🚀 **Optimalisasi UX** — hasil BMI hanya muncul setelah tombol **“Hitung BMI”** ditekan.
- 🧰 **Penambahan file `colors.xml` dan drawable gradient** untuk tema.
---
## 📜 Lisensi
Proyek ini dibuat untuk tujuan pembelajaran dalam mata kuliah **Pemrograman Perangkat Bergerak** dan tidak untuk tujuan komersial.
Lisensi mengikuti [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).
---

View File

@ -45,14 +45,13 @@ fun BmiCalculatorLayout() {
var weightInput by remember { mutableStateOf("") }
var useMetricSystem by remember { mutableStateOf(true) } // ✅ toggle sistem satuan
var errorMessage by remember { mutableStateOf("") }
var showResult by remember { mutableStateOf(false) } // ✅ hasil hanya tampil setelah tombol ditekan
var showResult by remember { mutableStateOf(false) }
val height = heightInput.toFloatOrNull() ?: 0f
val weight = weightInput.toFloatOrNull() ?: 0f
val isValid = validateInput(height, weight, useMetricSystem)
// Konversi tinggi & berat ke sistem metrik (meter & kg)
val heightInMeters = if (useMetricSystem) height / 100f else height * 0.0254f
val weightInKg = if (useMetricSystem) weight else weight * 0.453592f
@ -176,7 +175,6 @@ fun BmiCalculatorLayout() {
)
}
// Pesan error
if (errorMessage.isNotEmpty()) {
Text(
text = errorMessage,
@ -186,7 +184,7 @@ fun BmiCalculatorLayout() {
)
}
// Hasil BMI hanya tampil setelah ditekan tombol
// Hasil BMI
if (showResult && isValid) {
val categoryColor = when (category) {
"Kurus" -> MaterialTheme.colorScheme.tertiaryContainer
@ -217,10 +215,34 @@ fun BmiCalculatorLayout() {
}
}
}
// 📘 Panduan Kategori BMI
Spacer(modifier = Modifier.height(24.dp))
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = 6.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Panduan Kategori BMI",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.primary
)
Spacer(modifier = Modifier.height(8.dp))
Divider()
Spacer(modifier = Modifier.height(8.dp))
Text("• Kurus : BMI < 18.5")
Text("• Normal : 18.5 ≤ BMI < 25")
Text("• Kelebihan Berat : 25 ≤ BMI < 30")
Text("• Obesitas : BMI ≥ 30")
}
}
}
}
}
@Composable
fun EditNumberField(
@StringRes label: Int,
@ -257,6 +279,16 @@ fun validateInput(height: Float, weight: Float, useMetric: Boolean): Boolean {
height >= 4f && height <= 100f && weight in 5f..550f
}
fun calculateBMI(weight: Float, height: Float, useMetric: Boolean = true): Float {
if (height <= 0) return 0f
val heightInMeters = if (useMetric) height / 100f else height * 0.0254f
val weightInKg = if (useMetric) weight else weight * 0.453592f
return weightInKg / heightInMeters.pow(2)
}
@Preview(showBackground = true)
@Composable
fun BmiCalculatorPreview() {

View File

@ -1,9 +1,9 @@
package com.example.tiptime
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@ -11,11 +11,9 @@ class SplashActivity : AppCompatActivity() {
setContentView(R.layout.activity_splash)
val btnMulai = findViewById<Button>(R.id.btnMulai)
btnMulai.setOnClickListener {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
//finish() // supaya tidak bisa kembali ke splash dengan tombol back
startActivity(Intent(this, MainActivity::class.java))
//finish()
}
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#1FFFFFFF" />
<stroke android:color="#40FFFFFF" android:width="2dp"/>
</shape>

View File

@ -1,13 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:type="linear"
android:angle="270"
android:startColor="#4A90E2"
android:centerColor="#6A5ACD"
android:endColor="#8A2BE2"
android:useLevel="false" />
android:startColor="@color/purple_200"
android:centerColor="@color/teal_200"
android:endColor="@color/purple_700"
android:angle="270" />
</shape>

View File

@ -1,18 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:gravity="center"
android:padding="24dp"
android:background="@drawable/splash_gradient">
android:background="@drawable/splash_gradient"
tools:context=".SplashActivity">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_width="160dp"
android:layout_height="160dp"
android:src="@mipmap/ic_launcher_round"
android:contentDescription="Foto Profil"
android:layout_marginBottom="16dp" />
android:layout_marginBottom="20dp"
android:padding="16dp" />
<TextView
android:id="@+id/tvName"
@ -20,12 +24,12 @@
android:layout_height="wrap_content"
android:text="Rafi Fattan Fitriardi"
android:textStyle="bold"
android:textSize="20sp"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textColor="@android:color/white"
android:shadowColor="#80000000"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="2"
android:shadowDx="2"
android:shadowDy="2"
android:shadowRadius="4"
android:layout_marginBottom="8dp" />
<TextView
@ -33,12 +37,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="202310715002"
android:textSize="16sp"
android:textColor="#E0E0E0"
android:shadowColor="#80000000"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="2"
android:textSize="18sp"
android:textColor="#F0F0F0"
android:layout_marginBottom="8dp" />
<TextView
@ -47,20 +47,18 @@
android:layout_height="wrap_content"
android:text="Pemrograman Perangkat Bergerak - F5A5"
android:textSize="16sp"
android:textColor="#E0E0E0"
android:shadowColor="#80000000"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="2"
android:layout_marginBottom="24dp" />
android:textColor="#EDEDED"
android:layout_marginBottom="32dp" />
<Button
android:id="@+id/btnMulai"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MULAI"
android:backgroundTint="#4CAF50"
android:textColor="@android:color/white"
android:paddingHorizontal="32dp"
android:paddingVertical="12dp" />
android:backgroundTint="@android:color/holo_green_dark"
android:elevation="6dp"
android:paddingHorizontal="36dp"
android:paddingVertical="14dp"
android:fontFamily="sans-serif-medium" />
</LinearLayout>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Warna tema dasar -->
<color name="purple_200">#BB86FC</color>
<color name="purple_500">#6200EE</color>
<color name="purple_700">#3700B3</color>
<color name="teal_200">#03DAC5</color>
<color name="teal_700">#018786</color>
<color name="black">#000000</color>
<color name="white">#FFFFFF</color>
<!-- Gradasi untuk splash screen -->
<color name="gradient_start">#4CAF50</color> <!-- hijau terang -->
<color name="gradient_center">#81C784</color> <!-- hijau lembut -->
<color name="gradient_end">#C8E6C9</color> <!-- hijau muda -->
</resources>

View File

@ -4,8 +4,7 @@ import org.junit.Assert.assertEquals
import org.junit.Test
/**
* Unit test untuk memastikan fungsi perhitungan dan kategori BMI
* berjalan dengan benar.
* Unit test untuk memastikan fungsi perhitungan dan kategori BMI berjalan dengan benar.
*
* Lokasi file: app/src/test/java/com/example/tiptime/BmiUnitTest.kt
*/
@ -13,15 +12,15 @@ class BmiUnitTest {
@Test
fun calculateBMI_isAccurate() {
// Data: berat 70 kg, tinggi 170 cm
val result = calculateBMI(70f, 170f)
// Data: berat 70 kg, tinggi 170 cm (sistem metrik)
val result = calculateBMI(70f, 170f, true)
// Hasil ekspektasi ≈ 24.22
assertEquals(24.22f, result, 0.01f)
}
@Test
fun calculateBMI_zeroHeight_returnsZero() {
val result = calculateBMI(70f, 0f)
val result = calculateBMI(70f, 0f, true)
assertEquals(0f, result, 0.0f)
}
@ -51,13 +50,13 @@ class BmiUnitTest {
@Test
fun validateInput_validValues_returnsTrue() {
val isValid = validateInput(170f, 65f)
val isValid = validateInput(170f, 65f, true)
assertEquals(true, isValid)
}
@Test
fun validateInput_invalidValues_returnsFalse() {
val isValid = validateInput(5f, 500f)
val isValid = validateInput(5f, 500f, true)
assertEquals(false, isValid)
}
}