PBB VII - WaterBottle

Nama  : Nuzul Abatony
NRP    : 5025201107
Kelas   : I


Pada pertemuan kali ini, kami mempelajari material design dan kemudian membuat project sederhana bernama water bottle: PPB Tutorial

Berikut adalah link repository dari project yang dibuat: Link

Dengan hasil akhir seperti berikut: Video

Dengan cuplikan kode seperti berikut:
package com.example.waterbottle

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.clipPath
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

@Composable
fun WaterBottle(
modifier: Modifier = Modifier,
totalWaterAmount: Int,
unit: String,
usedWaterAmount: Int,
waterColor: Color = Color(0xff9fef00),
bottleColor: Color = Color.White,
capColor: Color = Color(0xff1a2435)
) {

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

val bottleBodyPath = Path().apply {
moveTo(
x = width * 0.3f, y = height * 0.1f
)
lineTo(
x = width * 0.3f, y = height * 0.2f
)
quadraticBezierTo(
x1 = 0f, y1 = height * 0.3f,
x2 = 0f, y2 = height * 0.4f
)
lineTo(
x = 0f,
y = height * 0.95f
)
quadraticBezierTo(
x1 = 0f, y1 = height,
x2 = width * 0.05f, y2 = height
)
lineTo(
x = width * 0.95f,
y = height
)
quadraticBezierTo(
x1 = width, y1 = height,
x2 = width, y2 = height * 0.95f
)
lineTo(
x = width,
y = height * 0.4f
)
quadraticBezierTo(
x1 = width, y1 = height * 0.3f,
x2 = width * 0.7f, y2 = height * 0.2f
)
lineTo(
x = width * 0.7f,
y = 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)
)
}

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

Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center){
Text(text = text)
}
}
}

Comments

Popular posts from this blog

PPB X - Dessert Clicker

PPB XII - Music Flutter App