Tugas Tambahan PPB G - Membuat Aplikasi Botol Air Sederhana Menggunakan Jetpack Compose
Tugas Pertemuan Terlewat Karena Libur MayDay PPB G 2025
Struktur File Utama
-
MainActivity.kt
→ Menangani UI utama dan interaksi pengguna. -
WaterBottle.kt
→ Komponen visual khusus yang menampilkan animasi botol air.
1. MainActivity.kt
Fungsi Utama
MainActivity
adalah entry point aplikasi yang menampilkan UI utama menggunakan Jetpack Compose.
Fitur:
-
Menampilkan jumlah air yang telah diminum dan total kapasitas botol.
-
Menyediakan tombol "Drink" untuk menambah 200ml air ke jumlah yang telah digunakan.
var usedAmount by remember{
mutableStateOf(400)
}
val totalWaterAmount = remember{
2400
}
usedAmount
menyimpan jumlah air yang telah diminum.-
totalWaterAmount
adalah kapasitas total botol (2400ml). -
Saat tombol "Drink" ditekan,
usedAmount
bertambah 200ml dan UI akan diperbarui otomatis.
WaterBottle(totalWaterAmount = totalWaterAmount, unit = "ml", usedWaterAmount = usedAmount)
Spacer(modifier = Modifier.height(20.dp))
Text(text = "Total amount is : ${totalWaterAmount} mililitres")
Button(onClick = { usedAmount += 200}){
Text(text = "Drink")
}
WaterBottle
untuk menggambar animasi botol sesuai jumlah air.2. WaterBottle.kt
Fungsi Utama
Menampilkan ilustrasi botol air dengan animasi naik-turun permukaan air berdasarkan jumlah air yang telah diminum (usedWaterAmount
).
Parameter:
modifier: Modifier = Modifier,
totalWaterAmount: Int,
unit: String,
usedWaterAmount: Int,
waterColor: Color = Color(0xff279eff),
bottleColor: Color = Color.White,
capColor: Color = Color(0xff0065b9)
-
totalWaterAmount
: Kapasitas botol (misal 2400ml). -
usedWaterAmount
: Jumlah air yang sudah diminum. -
unit
: Satuan air (misal"ml"
). -
waterColor
,bottleColor
,capColor
: Warna untuk air, botol, dan tutup botol.
Animasi:
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
-
animateFloatAsState
: Menganimasikan tinggi air berdasarkan persentase penggunaan. -
animateIntAsState
: Menganimasikan angka mililiter di tengah botol.
Visualisasi Botol:
Canvas(modifier= Modifier.fillMaxSize()){
val width = size.width // max width dari canvas
val height = size.height // max height dari canvas
val capWidth = size.width * 0.55f
val capHeight = size.height * 0.13f
val bottleBodyPath = Path().apply{
moveTo(width * 0.3f, height * 0.1f)
lineTo(width * 0.3f, height * 0.2f)
quadraticTo(0f, height * 0.3f, 0f, height * 0.4f)
lineTo(0f, height * 0.95f)
quadraticTo(0f, height, width * 0.05f, height)
lineTo(width * 0.95f, height)
quadraticTo(width, height, width, height * 0.95f)
lineTo(width, height * 0.4f)
quadraticTo(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 (
bottleBodyPath
){
drawRect(
color = bottleColor,
size = size,
)
val waterWavesYPosition = (1 - waterPercentage) * size.height
val waterPath = 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 = waterPath,
color = waterColor,
)
}
drawRoundRect(
color = capColor,
size = Size(capWidth, capHeight),
topLeft = Offset(size.width / 2 - capWidth / 2f, 0f),
cornerRadius = CornerRadius(45f, 45f)
)
}
-
Menggunakan
Canvas
untuk menggambar:-
Bentuk botol (menggunakan
Path
) -
Air (menggunakan
drawPath
) -
Tutup botol (menggunakan
drawRoundRect
)
-
-
Menggunakan
clipPath
untuk memastikan air hanya muncul di dalam bentuk botol.
Comments
Post a Comment