Tugas 8: Membuat Animasi Botol Air

Pada kesempatan ini, kita akan melakukan tinjauan mendalam terhadap kode yang mengimplementasikan sebuah komponen visual berupa botol air. Komponen ini tidak hanya statis, tetapi juga interaktif, lengkap dengan animasi yang halus untuk merepresentasikan tingkat keterisian air. Kode ini terbagi menjadi dua bagian utama: definisi komponen WatterBottle dan implementasinya di dalam MainActivity.

Bagian 1: Anatomi Komponen WatterBottle.kt

File ini merupakan cetak biru dari komponen botol air itu sendiri. Fungsinya adalah untuk menjadi sebuah elemen UI yang dapat digunakan kembali (reusable) di berbagai bagian aplikasi.

@Composable
fun WatterBottle(
    modifier: Modifier = Modifier,
    totalWaterAmount: Int,
    unit: String,
    usedWaterAmount: Int,
    //... parameter lainnya
) 

Fungsi Composable WatterBottle menerima beberapa parameter kunci:

  • totalWaterAmount: Kapasitas maksimal botol.
  • usedWaterAmount: Jumlah air yang telah terisi atau dikonsumsi.
  • unit: Satuan ukur yang digunakan (misalnya, "ml").
  • Warna-warna kustom untuk personalisasi tampilan.

Kunci Utama: Animasi dan Penggambaran Kustom

Keunggulan utama komponen ini terletak pada penggunaan Canvas dan API animasi dari Jetpack Compose.

  1. Animasi Halus (animateFloatAsState & animateIntAsState):

    Daripada mengubah nilai ketinggian air dan teks secara tiba-tiba, kode ini memanfaatkan animate...AsState.

    • waterPercentage: Variabel ini secara mulus menganimasikan nilai float antara 0.0f hingga 1.0f berdasarkan persentase air yang terisi. tween(durationMillis = 500) memastikan transisi ini terjadi dalam 500 milidetik, memberikan efek visual yang memanjakan mata.
    • usedWaterAmountAnimation: Serupa dengan sebelumnya, ini menganimasikan perubahan angka pada teks, sehingga angka tidak "melompat", melainkan bertransisi dengan halus.
  2. Penggambaran dengan Canvas:

    Untuk menciptakan bentuk botol yang tidak standar, Canvas adalah pilihan yang tepat.

    • Bentuk Botol (bodyPath): Path digunakan untuk "menggambar" outline atau kerangka dari botol. Perintah seperti moveTo, lineTo, dan quadraticBezierTo digunakan untuk membuat garis lurus dan kurva yang membentuk siluet botol.
    • Teknik Kliping (clipPath): Ini adalah konsep yang sangat penting. Setelah bodyPath didefinisikan, ia digunakan sebagai "pemotong" atau topeng. Semua yang digambar di dalam blok clipPath hanya akan terlihat di dalam area yang dibatasi oleh bodyPath tersebut. Inilah yang membuat air tampak berada "di dalam" botol.
    • Visualisasi Air (wavesPath): Di dalam clipPath, sebuah path sederhana digambar untuk merepresentasikan air. Posisi vertikal bagian atasnya dikontrol oleh waterWavesYPosition, yang nilainya bergantung pada variabel waterPercentage yang dianimasikan. Saat usedWaterAmount bertambah, waterPercentage meningkat, dan posisi y dari "air" ini akan bergerak ke atas, menciptakan ilusi pengisian.
  3. Teks yang Adaptif (buildAnnotatedString):

    Teks yang menunjukkan jumlah air ditempatkan di tengah. Implementasinya cukup cerdas:

    • Menggunakan buildAnnotatedString untuk menggabungkan teks dengan gaya yang berbeda (jumlah air dengan font besar, dan unit "ml" dengan font lebih kecil).
    • Warna teks secara dinamis berubah. Jika level air (waterPercentage) sudah melewati setengah, warna teks akan kontras dengan warna air agar tetap terbaca. Ini adalah detail kecil yang sangat meningkatkan pengalaman pengguna (UX).

Bagian 2: Implementasi di MainActivity.kt

File ini berfungsi sebagai "panggung" di mana komponen WatterBottle ditampilkan dan dihidupkan.

Manajemen Keadaan (State Management)

var usedWaterAmount by remember { mutableStateOf(0) }
val totalWaterAmount = remember { 2500 }

usedWaterAmount dideklarasikan sebagai sebuah state (mutableStateOf). Ini adalah "sumber kebenaran" (source of truth). Setiap kali nilai ini berubah, Jetpack Compose secara otomatis akan "menggambar ulang" (recompose) semua komponen yang menggunakan state ini. Kata kunci remember memastikan bahwa state ini tidak direset setiap kali terjadi recomposition.

Interaktivitas Pengguna

Di bawah komponen WatterBottle, terdapat dua Button: "Drink" dan "Reset".

  • Tombol "Drink": Saat diklik, tombol ini akan memperbarui state usedWaterAmount dengan menambahkannya sebanyak 200. Fungsi coerceAtMost(totalWaterAmount) adalah sebuah pengaman untuk memastikan nilai tidak melebihi kapasitas total botol.
  • Tombol "Reset": Tombol ini mengembalikan state usedWaterAmount ke nilai 0.

Kedua tombol ini menunjukkan prinsip fundamental dari UI deklaratif: Anda tidak memanipulasi UI secara langsung. Anda mengubah state, dan UI akan bereaksi sesuai perubahan state tersebut.

Kesimpulan

Kode ini adalah contoh yang sangat baik tentang kekuatan Jetpack Compose. Ia mendemonstrasikan bagaimana konsep-konsep inti seperti:

  • Composable Functions untuk membangun UI modular.
  • State Management dengan remember dan mutableStateOf untuk menggerakkan data.
  • API Animasi untuk menciptakan pengalaman pengguna yang dinamis dan hidup.
  • Custom Drawing dengan Canvas dan Path untuk melampaui batas komponen UI standar.

Dengan memadukan logika ini, developer dapat membangun antarmuka yang tidak hanya fungsional tetapi juga indah secara visual dan interaktif, langsung dari dalam kode Kotlin.

Github
Referensi:
https://kuliahppb.blogspot.com/2024/05/activity-dan-intent.html
https://www.youtube.com/watch?v=vmT0SScA2lA
https://github.com/mohammednawas8/WaterBottel

Komentar

Postingan populer dari blog ini

Tugas 10: Membuat Aplikasi Unscramble

ETS Proyek 5: Aplikasi Galeri Foto Pribadi

Evaluasi Akhir Semester