Anonymous
Ошибка размера анимированной бутылки с водой при составлении реактивного ранца
Сообщение
Anonymous » 23 июн 2024, 18:30
Этот код рассчитывает количество воды, которое человек должен выпивать ежедневно. и при нажатии на кнопку убавляет воду из полной бутылки.
На самом деле в программе все работает четко, но при первом нажатии уровень воды не меняется как результат клика. После первого нажатия все работает нормально. Я не могу справиться с этим, вы можете мне помочь?
Код: Выделить всё
package com.example.diettrackingapp.home
import android.widget.Toast
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.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
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.platform.LocalContext
import androidx.compose.ui.platform.LocalConfiguration
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
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.diettrackingapp.firebase.PatientViewModel
@Composable
fun WaterScreen() {
val context = LocalContext.current
var totalWaterAmount by remember { mutableStateOf(0) }
var usedWaterAmount by remember { mutableStateOf(0) }
val weight = 70
totalWaterAmount = (weight * 35)
val configuration = LocalConfiguration.current
val screenWidth = configuration.screenWidthDp.dp
Column(
modifier = Modifier
.width(screenWidth * 0.4f),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
Spacer(modifier = Modifier.height(25.dp))
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
WaterBottle(
modifier = Modifier
.width(screenWidth * 0.3f)
.height(screenWidth * 0.6f),
totalWaterAmount = totalWaterAmount,
unit = "ml",
usedWaterAmount = usedWaterAmount
)
Spacer(modifier = Modifier.height(10.dp))
Text(text = "Total:$totalWaterAmount ml")
Button(onClick = {
if (usedWaterAmount < totalWaterAmount) usedWaterAmount += 200 else Toast.makeText(
context, "Bottle is Empty", Toast.LENGTH_LONG
).show()
}) {
Text(text = "Drink")
}
}
}
}
@Composable
fun WaterBottle(
modifier: Modifier,
totalWaterAmount: Int,
unit: String,
usedWaterAmount: Int,
waterColor: Color = Color(0xFF1F97F8),
bottleColor: Color = Color.White,
capColor: Color = Color(0xFF01355F)
) {
val waterPercentage by animateFloatAsState(
targetValue = if (totalWaterAmount > 0) usedWaterAmount.toFloat() / totalWaterAmount.toFloat() else 0f,
animationSpec = tween(1000), label = ""
)
val usedWaterAnimation by animateIntAsState(
targetValue = usedWaterAmount, animationSpec = tween(1000), label = ""
)
Box(
modifier = modifier
.clip(RoundedCornerShape(10.dp))
.background(Color(0xFFFDF7BA))
.padding(10.dp)
) {
Canvas(modifier = Modifier.fillMaxSize()) {
val width = size.width
val height = size.height
val capWidth = size.width * 0.55f
val capHeight = size.height * 0.08f
val bottleBodyPath = Path().apply {
moveTo(width * 0.3f, height * 0.1f)
lineTo(
width * 0.3f, height * 0.2f
)
quadraticBezierTo(
0f, height * 0.3f, 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.1f
)
close()
}
clipPath(
bottleBodyPath
) {
drawRect(
color = bottleColor, size = size
)
val waterWavesYPosition = waterPercentage * size.height
val waterPath = Path().apply {
moveTo(0f, waterWavesYPosition)
lineTo(
size.width, waterWavesYPosition
)
lineTo(
size.width, size.height
)
lineTo(
0f, size.height
)
close()
}
drawPath(
waterPath, waterColor
)
}
drawRoundRect(
color = capColor,
size = Size(capWidth, capHeight),
topLeft = Offset(size.width / 2 - capWidth / 2f, 0f),
cornerRadius = CornerRadius(45f, 45f)
)
}
val fontSize = with(LocalConfiguration.current) { screenWidthDp * 0.03 }.sp
val text = buildAnnotatedString {
withStyle(
SpanStyle(
color = Color.Black,
fontSize = fontSize
)
) {
append("Drunk Water:\n")
}
withStyle(
style = SpanStyle(
color = Color.Black,
fontSize = fontSize * 2
)
) {
append(usedWaterAnimation.toString())
}
withStyle(
style = SpanStyle(
color = Color.Black,
fontSize = fontSize
)
) {
append(" ")
append(unit)
}
}
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(text = text)
}
}
}
Подробнее здесь:
https://stackoverflow.com/questions/786 ... ck-compose
1719156631
Anonymous
Этот код рассчитывает количество воды, которое человек должен выпивать ежедневно. и при нажатии на кнопку убавляет воду из полной бутылки. На самом деле в программе все работает четко, но при первом нажатии уровень воды не меняется как результат клика. После первого нажатия все работает нормально. Я не могу справиться с этим, вы можете мне помочь? [code] package com.example.diettrackingapp.home import android.widget.Toast 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.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.scale 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.platform.LocalContext import androidx.compose.ui.platform.LocalConfiguration 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 import androidx.lifecycle.viewmodel.compose.viewModel import com.example.diettrackingapp.firebase.PatientViewModel @Composable fun WaterScreen() { val context = LocalContext.current var totalWaterAmount by remember { mutableStateOf(0) } var usedWaterAmount by remember { mutableStateOf(0) } val weight = 70 totalWaterAmount = (weight * 35) val configuration = LocalConfiguration.current val screenWidth = configuration.screenWidthDp.dp Column( modifier = Modifier .width(screenWidth * 0.4f), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Top ) { Spacer(modifier = Modifier.height(25.dp)) Column( horizontalAlignment = Alignment.CenterHorizontally ) { WaterBottle( modifier = Modifier .width(screenWidth * 0.3f) .height(screenWidth * 0.6f), totalWaterAmount = totalWaterAmount, unit = "ml", usedWaterAmount = usedWaterAmount ) Spacer(modifier = Modifier.height(10.dp)) Text(text = "Total:$totalWaterAmount ml") Button(onClick = { if (usedWaterAmount < totalWaterAmount) usedWaterAmount += 200 else Toast.makeText( context, "Bottle is Empty", Toast.LENGTH_LONG ).show() }) { Text(text = "Drink") } } } } @Composable fun WaterBottle( modifier: Modifier, totalWaterAmount: Int, unit: String, usedWaterAmount: Int, waterColor: Color = Color(0xFF1F97F8), bottleColor: Color = Color.White, capColor: Color = Color(0xFF01355F) ) { val waterPercentage by animateFloatAsState( targetValue = if (totalWaterAmount > 0) usedWaterAmount.toFloat() / totalWaterAmount.toFloat() else 0f, animationSpec = tween(1000), label = "" ) val usedWaterAnimation by animateIntAsState( targetValue = usedWaterAmount, animationSpec = tween(1000), label = "" ) Box( modifier = modifier .clip(RoundedCornerShape(10.dp)) .background(Color(0xFFFDF7BA)) .padding(10.dp) ) { Canvas(modifier = Modifier.fillMaxSize()) { val width = size.width val height = size.height val capWidth = size.width * 0.55f val capHeight = size.height * 0.08f val bottleBodyPath = Path().apply { moveTo(width * 0.3f, height * 0.1f) lineTo( width * 0.3f, height * 0.2f ) quadraticBezierTo( 0f, height * 0.3f, 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.1f ) close() } clipPath( bottleBodyPath ) { drawRect( color = bottleColor, size = size ) val waterWavesYPosition = waterPercentage * size.height val waterPath = Path().apply { moveTo(0f, waterWavesYPosition) lineTo( size.width, waterWavesYPosition ) lineTo( size.width, size.height ) lineTo( 0f, size.height ) close() } drawPath( waterPath, waterColor ) } drawRoundRect( color = capColor, size = Size(capWidth, capHeight), topLeft = Offset(size.width / 2 - capWidth / 2f, 0f), cornerRadius = CornerRadius(45f, 45f) ) } val fontSize = with(LocalConfiguration.current) { screenWidthDp * 0.03 }.sp val text = buildAnnotatedString { withStyle( SpanStyle( color = Color.Black, fontSize = fontSize ) ) { append("Drunk Water:\n") } withStyle( style = SpanStyle( color = Color.Black, fontSize = fontSize * 2 ) ) { append(usedWaterAnimation.toString()) } withStyle( style = SpanStyle( color = Color.Black, fontSize = fontSize ) ) { append(" ") append(unit) } } Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text(text = text) } } } [/code] [img]https://i.sstatic.net/BH1P1Eoz.png[/img] Подробнее здесь: [url]https://stackoverflow.com/questions/78657341/animated-bottle-water-size-error-in-jetpack-compose[/url]