Tugas 8 - Water Bottle

https://github.com/ilomimo/water-bottle-ppb


Aplikasi Water Bottle Tracker adalah aplikasi Android berbasis Jetpack Compose yang dirancang untuk membantu pengguna memantau konsumsi air harian mereka secara visual dan interaktif. Aplikasi ini menyajikan simulasi botol air yang dapat diisi dan diminum secara bertahap dengan tampilan modern berbasis Material Design 3. Fokus utama aplikasi ini adalah pada interaksi pengguna yang intuitif, desain visual realistis, serta state management yang efisien menggunakan fitur remember dan LaunchedEffect dari Jetpack Compose. Proyek ini tidak hanya membantu meningkatkan keterampilan pemrograman UI, tetapi juga memperkenalkan praktik terbaik dalam pengelolaan state, desain responsif, dan animasi transisi yang smooth.

Fitur Utama

  1. Simulasi Botol Air
    • Botol ditampilkan dengan bentuk visual mirip botol Pocari Sweat: memiliki leher, bahu, badan, serta tekstur horizontal khas.
    • Botol berisi air yang naik dan turun sesuai aksi pengguna.
  2. Pengisian dan Pemakaian Air
    • Tombol Fill untuk mengisi air secara bertahap hingga penuh.
    • Tombol Drink untuk mengurangi 100ml air tiap kali ditekan.
    • Air tidak langsung habis, tetapi dikontrol penuh oleh pengguna (manual step-by-step).
  3. Indikator Volume dan Total
    • Menampilkan jumlah air saat ini dalam botol dalam satuan ml.
    • Menyimpan dan menampilkan total air yang sudah diminum secara kumulatif.

Penerapan Material Design

Desain aplikasi mengikuti prinsip Material Design 3:

  • Menggunakan elemen Surface, Card, Button, dan Text dengan warna dari MaterialTheme.colorScheme.
  • Background menggunakan gradasi lembut biru muda untuk menciptakan suasana segar.
  • Ukuran, padding, dan penempatan elemen mengikuti guideline Material agar responsif dan rapi.

Potongan Kode Utama

1.

State Management dan Animasi

var fillLevel by remember { mutableFloatStateOf(0f) }
var totalDrank by remember { mutableIntStateOf(0) }
var drinkRequested by remember { mutableStateOf(false) }
val animatedFill by animateFloatAsState(targetValue = fillLevel, label = "animatedFill")
val currentAmount = (animatedFill * 1000).toInt()

2.

Logika Minum Bertahap

LaunchedEffect(drinkRequested) {
    if (drinkRequested && fillLevel > 0f) {
        val step = 100f / 1000f
        fillLevel = (fillLevel - step).coerceAtLeast(0f)
        totalDrank += 100
        drinkRequested = false
    }
}

3.

Tampilan Botol Air (Canvas)

Canvas(modifier = Modifier.fillMaxSize()) {
    val fillHeight = bodyHeight * animatedFill.coerceIn(0f, 1f)

    // Badan botol
    drawRoundRect(
        color = Color(0xFFB0BEC5),
        topLeft = Offset(0f, bodyTop),
        size = Size(width, bodyHeight),
        cornerRadius = CornerRadius(40f, 40f),
        style = Stroke(width = 6f)
    )

    // Tekstur horizontal
    for (i in 1..6) {
        val y = bodyTop + (bodyHeight * i / 7f)
        drawLine(
            color = Color.White.copy(alpha = 0.3f),
            start = Offset(width * 0.15f, y),
            end = Offset(width * 0.85f, y),
            strokeWidth = 2f
        )
    }

    // Air di dalam botol
    drawRoundRect(
        color = Color(0xFF0288D1),
        topLeft = Offset(0f, bodyTop + bodyHeight - fillHeight),
        size = Size(width, fillHeight),
        cornerRadius = CornerRadius(30f, 30f)
    )
}

4.Tombol Interaktif

Button(onClick = { fillLevel = if (fillLevel >= 1f) 0f else fillLevel + 0.1f }) {
    Text("Fill")
}

Button(onClick = { if (fillLevel > 0f) drinkRequested = true }) {
    Text("Drink")
}


Comments

Popular posts from this blog

EAS PPB

Tugas Pertemuan 12 - Dessert Clicker

Tugas Pertemuan 13: Membuat Aplikasi Unscramble