Pertemuan 8_Water Bottle

Nama              : Al-Ferro Yudisthira Putra

NRP                : 5025211176

Kelas               : PPB - A


Water Bottle App

Pada pertemuan ini, diberikan sebuah tugas untuk membuat sebuah aplikasi sederhana yang bersifat interaktif. Aplikasi ini memuat sebuah visual botol air minum. Ketika tombol Drink ditekan, maka jumlah mililiter air akan bertambah seperti divisualisasikan pada gambar dibawah.

Jumlah mililiter air bertambah menjadi 5000 ml ketika tombol Drink ditekan. Untuk mendapatkan hasil seperti ini, maka dijelaskan dibawah mengenai code pembangun aplikasi ini.

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
WaterbottleTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {

var usedWaterAmount by remember {
mutableStateOf(100)
}
val totalWaterAmount = remember {
2500
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {

WatterBottle(
totalWaterAmount = totalWaterAmount,
unit = "ml",
usedWaterAmount = usedWaterAmount
)
Spacer(modifier = Modifier.height(20.dp))
Text(
text = "Total Amount is : $totalWaterAmount",
textAlign = TextAlign.Center
)
Button(
onClick = { usedWaterAmount += 200 },
colors = ButtonDefaults.buttonColors(containerColor =
Color(0xff279EFF))
) {
Text(text = "Drink")
}
}


}
}
}
}
}
Di dalam kelas MainActivity, komponen UI didefinisikan menggunakan fungsi setContent. Seluruh tampilan dibungkus dengan tema khusus bernama WaterbottleTheme, dan terdapat elemen Surface sebagai wadah utama yang mengisi seluruh layar dengan warna latar belakang sesuai tema. Di dalamnya, terdapat state usedWaterAmount yang menyimpan jumlah air yang sudah diminum dan dapat berubah secara dinamis, serta totalWaterAmount sebagai total kapasitas air yang ditentukan tetap sebanyak 2500 ml. Komponen UI disusun menggunakan Column yang menempatkan semua elemen secara vertikal di tengah layar. Komponen kustom WatterBottle digunakan untuk menampilkan visualisasi atau informasi terkait status air. Selanjutnya terdapat teks yang menunjukkan total kapasitas air, serta tombol "Drink" yang jika ditekan akan menambah nilai usedWaterAmount sebanyak 200 ml. Karena menggunakan konsep state Compose, setiap kali nilai usedWaterAmount berubah, bagian UI yang bergantung pada nilai ini akan otomatis diperbarui tanpa perlu memanggil fungsi tambahan. Dengan demikian, aplikasi ini memanfaatkan keunggulan Jetpack Compose dalam membangun UI yang deklaratif, reaktif, dan efisien.

fun WatterBottle(
modifier: Modifier = Modifier,
totalWaterAmount: Int,
unit: String,
usedWaterAmount: Int,
waterWavesColor: Color = Color(0xff279EFF),
bottleColor: Color = Color.White,
capColor: Color = Color(0xFF0065B9)
) {

val waterPercentage = animateFloatAsState(
targetValue = (usedWaterAmount.toFloat() / totalWaterAmount.toFloat()),
label = "Water Waves animation",
animationSpec = tween(durationMillis = 1000)
).value

val usedWaterAmountAnimation = animateIntAsState(
targetValue = usedWaterAmount,
label = "Used water amount animation",
animationSpec = tween(durationMillis = 1000)
).value

Box(
modifier = modifier
.width(200.dp)
.height(600.dp)
) {

Canvas(modifier = Modifier.fillMaxSize()) {
val width = size.width
val height = size.height

val capWidth = size.width * 0.55f
val capHeight = size.height * 0.13f

//Draw the bottle body
val bodyPath = Path().apply {
moveTo(width * 0.3f, height * 0.1f)
lineTo(width * 0.3f, height * 0.2f)
quadraticBezierTo(
0f, height * 0.3f, // The pulling point
0f, height * 0.4f
)
lineTo(0f, height * 0.95f)
quadraticBezierTo(
0f, height,
width * 0.05f, height
)

lineTo(width * 0.95f, height)
quadraticBezierTo(
width, height,
width, height * 0.95f
)
lineTo(width, height * 0.4f)
quadraticBezierTo(
width, height * 0.3f,
width * 0.7f, height * 0.2f
)
lineTo(width * 0.7f, height * 0.2f)
lineTo(width * 0.7f, height * 0.1f)

close()
}
clipPath(
path = bodyPath
) {
// Draw the color of the bottle
drawRect(
color = bottleColor,
size = size,
topLeft = Offset(0f, 0f)
)

//Draw the water waves
val waterWavesYPosition = (1 - waterPercentage) * size.height

val wavesPath = Path().apply {
moveTo(
x = 0f,
y = waterWavesYPosition
)
lineTo(
x = size.width,
y = waterWavesYPosition
)
lineTo(
x = size.width,
y = size.height
)
lineTo(
x = 0f,
y = size.height
)
close()
}
drawPath(
path = wavesPath,
color = waterWavesColor,
)
}

//Draw the bottle cap
drawRoundRect(
color = capColor,
size = Size(capWidth, capHeight),
topLeft = Offset(size.width / 2 - capWidth / 2f, 0f),
cornerRadius = CornerRadius(45f, 45f)
)


}
val text = buildAnnotatedString {
withStyle(
style = SpanStyle(
color = if (waterPercentage > 0.5f) bottleColor else waterWavesColor,
fontSize = 44.sp
)
) {
append(usedWaterAmountAnimation.toString())
}
withStyle(
style = SpanStyle(
color = if (waterPercentage > 0.5f) bottleColor else waterWavesColor,
fontSize = 22.sp
)
) {
append(" ")
append(unit)
}
}

Box(
modifier = Modifier
.fillMaxSize()
.fillMaxHeight(),
contentAlignment = Alignment.Center
) {
Text(text = text)
}
}
}
Fungsi WatterBottle merupakan komponen kustom berbasis Jetpack Compose yang digunakan untuk menampilkan ilustrasi visual botol air lengkap dengan animasi isi air berdasarkan jumlah air yang sudah diminum oleh pengguna. Fungsi ini menerima beberapa parameter seperti totalWaterAmount (total kapasitas air), usedWaterAmount (jumlah air yang sudah diminum), unit (satuan air), serta warna-warna untuk botol, air, dan tutup botol. Di dalamnya, terdapat dua animasi yaitu waterPercentage yang menggambarkan persentase air dalam botol, dan usedWaterAmountAnimation yang menampilkan angka air yang sudah diminum dengan efek animasi transisi halus. Visual botol digambar menggunakan Canvas dengan bantuan Path untuk membentuk lekukan badan botol. Bagian isi air digambarkan sebagai gelombang sederhana yang naik turun mengikuti persentase air. Kemudian, bagian tutup botol juga digambarkan menggunakan drawRoundRect. Di tengah botol, terdapat teks yang menunjukkan jumlah air yang sudah diminum dalam satuan tertentu, di mana warna teks menyesuaikan kondisi air dalam botol agar tetap kontras dan mudah dibaca. Komponen ini memberikan efek visual yang interaktif dan menarik, memanfaatkan animasi dan penggambaran berbasis vektor agar UI terlihat dinamis dan responsif terhadap perubahan data.

GITHUB REPO

REFERENCE

Comments

Popular posts from this blog

Pertemuan 2 - Aplikasi Hello Android

Pertemuan 7 - UI/UX Login Page

Pertemuan 6_Aplikasi Currency Converter