feat: flying card animation - cards animate from hand to discard pile
This commit is contained in:
@@ -16,18 +16,158 @@ import androidx.compose.ui.draw.clip
|
|||||||
import androidx.compose.ui.draw.scale
|
import androidx.compose.ui.draw.scale
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Brush
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.IntOffset
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.uno.game.GameEngine
|
import com.uno.game.GameEngine
|
||||||
import com.uno.game.model.*
|
import com.uno.game.model.*
|
||||||
import kotlin.math.roundToInt
|
import kotlinx.coroutines.coroutineScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
// region --- Flying Card Animation ---
|
||||||
|
|
||||||
|
private data class FlyingCard(
|
||||||
|
val card: Card,
|
||||||
|
val fromX: Float,
|
||||||
|
val fromY: Float,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun rememberFlyingCardState(): FlyingCardState {
|
||||||
|
return remember { FlyingCardState() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FlyingCardState {
|
||||||
|
var flyingCard by mutableStateOf<FlyingCard?>(null)
|
||||||
|
private set
|
||||||
|
|
||||||
|
private var animatableX = Animatable(0f)
|
||||||
|
private var animatableY = Animatable(0f)
|
||||||
|
private var animatableScale = Animatable(0f)
|
||||||
|
private var animatableRotation = Animatable(0f)
|
||||||
|
|
||||||
|
val offsetX: Float get() = animatableX.value
|
||||||
|
val offsetY: Float get() = animatableY.value
|
||||||
|
val scale: Float get() = animatableScale.value
|
||||||
|
val rotation: Float get() = animatableRotation.value
|
||||||
|
|
||||||
|
suspend fun animateCard(card: Card, fromX: Float, fromY: Float) {
|
||||||
|
flyingCard = FlyingCard(card, fromX, fromY)
|
||||||
|
|
||||||
|
animatableX = Animatable(fromX)
|
||||||
|
animatableY = Animatable(fromY)
|
||||||
|
animatableScale = Animatable(0.3f)
|
||||||
|
animatableRotation = Animatable((Math.random() * 60 - 30).toFloat())
|
||||||
|
|
||||||
|
coroutineScope {
|
||||||
|
launch {
|
||||||
|
animatableX.animateTo(
|
||||||
|
targetValue = 0f,
|
||||||
|
animationSpec = spring(dampingRatio = 0.6f, stiffness = Spring.StiffnessLow)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
animatableY.animateTo(
|
||||||
|
targetValue = 0f,
|
||||||
|
animationSpec = spring(dampingRatio = 0.6f, stiffness = Spring.StiffnessLow)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
animatableScale.animateTo(
|
||||||
|
targetValue = 1f,
|
||||||
|
animationSpec = spring(dampingRatio = 0.5f, stiffness = Spring.StiffnessMedium)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
animatableRotation.animateTo(
|
||||||
|
targetValue = 0f,
|
||||||
|
animationSpec = spring(dampingRatio = 0.7f, stiffness = Spring.StiffnessLow)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(200)
|
||||||
|
animatableScale.animateTo(
|
||||||
|
targetValue = 0.8f,
|
||||||
|
animationSpec = tween(200, easing = FastOutSlowInEasing)
|
||||||
|
)
|
||||||
|
flyingCard = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reset() {
|
||||||
|
flyingCard = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun FlyingCardOverlay(
|
||||||
|
state: FlyingCardState,
|
||||||
|
screenCenterX: Float,
|
||||||
|
screenCenterY: Float
|
||||||
|
) {
|
||||||
|
val card = state.flyingCard ?: return
|
||||||
|
|
||||||
|
val backgroundColor = when (card.card.color) {
|
||||||
|
CardColor.RED -> Color(0xFFE53935)
|
||||||
|
CardColor.GREEN -> Color(0xFF43A047)
|
||||||
|
CardColor.BLUE -> Color(0xFF1E88E5)
|
||||||
|
CardColor.YELLOW -> Color(0xFFFDD835)
|
||||||
|
null -> Color(0xFF424242)
|
||||||
|
}
|
||||||
|
val textColor = if (card.card.color == CardColor.YELLOW) Color.Black else Color.White
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.pointerInput(Unit) { /* consume touch events */ },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.offset(
|
||||||
|
x = with(LocalDensity.current) { state.offsetX.toDp() },
|
||||||
|
y = with(LocalDensity.current) { state.offsetY.toDp() }
|
||||||
|
)
|
||||||
|
.graphicsLayer {
|
||||||
|
scaleX = state.scale
|
||||||
|
scaleY = state.scale
|
||||||
|
rotationZ = state.rotation
|
||||||
|
shadowElevation = 16f
|
||||||
|
}
|
||||||
|
.size(width = 60.dp, height = 90.dp)
|
||||||
|
.shadow(12.dp, RoundedCornerShape(8.dp))
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(backgroundColor)
|
||||||
|
.border(2.dp, Color.White.copy(alpha = 0.6f), RoundedCornerShape(8.dp))
|
||||||
|
.padding(6.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = card.card.displayValue,
|
||||||
|
color = textColor,
|
||||||
|
fontSize = 22.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
if (card.card.color != null) {
|
||||||
|
Text(text = card.card.color.displayName, color = textColor, fontSize = 9.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
// region --- Animations ---
|
// region --- Animations ---
|
||||||
|
|
||||||
@@ -130,10 +270,44 @@ fun UnoGameScreen(
|
|||||||
) {
|
) {
|
||||||
var showColorPicker by remember { mutableStateOf(false) }
|
var showColorPicker by remember { mutableStateOf(false) }
|
||||||
var pendingWildCard by remember { mutableStateOf<Card?>(null) }
|
var pendingWildCard by remember { mutableStateOf<Card?>(null) }
|
||||||
var previousTopCard by remember { mutableStateOf(state.deck.topCard) }
|
|
||||||
var showUnoCall by remember { mutableStateOf(false) }
|
var showUnoCall by remember { mutableStateOf(false) }
|
||||||
var previousLastAction by remember { mutableStateOf(state.lastAction) }
|
var previousLastAction by remember { mutableStateOf(state.lastAction) }
|
||||||
|
var previousTopCard by remember { mutableStateOf(state.deck.topCard) }
|
||||||
|
var lastPlayedByPlayerIndex by remember { mutableIntStateOf(0) }
|
||||||
|
|
||||||
|
val flyingState = rememberFlyingCardState()
|
||||||
|
|
||||||
|
// Track who played the last card
|
||||||
|
LaunchedEffect(state.currentPlayerIndex, state.deck.topCard) {
|
||||||
|
val newTop = state.deck.topCard
|
||||||
|
if (newTop != null && newTop != previousTopCard) {
|
||||||
|
// The card was played by the player whose turn it was BEFORE the index changed
|
||||||
|
val fromX = when (lastPlayedByPlayerIndex) {
|
||||||
|
0 -> 0f
|
||||||
|
1 -> 300f
|
||||||
|
2 -> 0f
|
||||||
|
3 -> -300f
|
||||||
|
else -> 0f
|
||||||
|
}
|
||||||
|
val fromY = when (lastPlayedByPlayerIndex) {
|
||||||
|
0 -> 400f
|
||||||
|
1 -> -200f
|
||||||
|
2 -> -400f
|
||||||
|
3 -> -200f
|
||||||
|
else -> 0f
|
||||||
|
}
|
||||||
|
|
||||||
|
flyingState.animateCard(newTop, fromX, fromY)
|
||||||
|
previousTopCard = newTop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update who is about to play
|
||||||
|
LaunchedEffect(state.currentPlayerIndex) {
|
||||||
|
lastPlayedByPlayerIndex = state.currentPlayerIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNO-Rufen Animation
|
||||||
LaunchedEffect(state.lastAction) {
|
LaunchedEffect(state.lastAction) {
|
||||||
if (state.lastAction != previousLastAction && state.lastAction.contains("UNO")) {
|
if (state.lastAction != previousLastAction && state.lastAction.contains("UNO")) {
|
||||||
showUnoCall = true
|
showUnoCall = true
|
||||||
@@ -143,10 +317,6 @@ fun UnoGameScreen(
|
|||||||
previousLastAction = state.lastAction
|
previousLastAction = state.lastAction
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(state.deck.topCard) {
|
|
||||||
previousTopCard = state.deck.topCard
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -166,6 +336,7 @@ fun UnoGameScreen(
|
|||||||
currentColor = state.currentColor,
|
currentColor = state.currentColor,
|
||||||
isCurrentTurn = state.currentPlayerIndex == 0,
|
isCurrentTurn = state.currentPlayerIndex == 0,
|
||||||
onCardClick = { card ->
|
onCardClick = { card ->
|
||||||
|
lastPlayedByPlayerIndex = 0
|
||||||
if (card.isWild) {
|
if (card.isWild) {
|
||||||
pendingWildCard = card
|
pendingWildCard = card
|
||||||
showColorPicker = true
|
showColorPicker = true
|
||||||
@@ -196,6 +367,13 @@ fun UnoGameScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fliegende Karte Overlay
|
||||||
|
FlyingCardOverlay(
|
||||||
|
state = flyingState,
|
||||||
|
screenCenterX = 0f,
|
||||||
|
screenCenterY = 0f
|
||||||
|
)
|
||||||
|
|
||||||
// UNO call overlay
|
// UNO call overlay
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = showUnoCall,
|
visible = showUnoCall,
|
||||||
@@ -261,28 +439,17 @@ private fun GameInfoBar(state: GameState) {
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Text(
|
Text("Richtung:", style = MaterialTheme.typography.bodyMedium)
|
||||||
text = "Richtung:",
|
|
||||||
style = MaterialTheme.typography.bodyMedium
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "↗️",
|
text = "↗️",
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
modifier = Modifier.graphicsLayer {
|
modifier = Modifier.graphicsLayer { rotationZ = directionRotation }
|
||||||
rotationZ = directionRotation
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text("Stapel: ${state.deck.drawPile.size}", style = MaterialTheme.typography.bodyMedium)
|
||||||
text = "Stapel: ${state.deck.drawPile.size}",
|
|
||||||
style = MaterialTheme.typography.bodyMedium
|
|
||||||
)
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Text(
|
Text("Farbe: ", style = MaterialTheme.typography.bodyMedium)
|
||||||
text = "Farbe: ",
|
|
||||||
style = MaterialTheme.typography.bodyMedium
|
|
||||||
)
|
|
||||||
state.currentColor?.let { color ->
|
state.currentColor?.let { color ->
|
||||||
val bgColor = when (color) {
|
val bgColor = when (color) {
|
||||||
CardColor.RED -> Color(0xFFE53935)
|
CardColor.RED -> Color(0xFFE53935)
|
||||||
@@ -291,10 +458,7 @@ private fun GameInfoBar(state: GameState) {
|
|||||||
CardColor.YELLOW -> Color(0xFFFDD835)
|
CardColor.YELLOW -> Color(0xFFFDD835)
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.size(14.dp).clip(RoundedCornerShape(3.dp)).background(bgColor)
|
||||||
.size(14.dp)
|
|
||||||
.clip(RoundedCornerShape(3.dp))
|
|
||||||
.background(bgColor)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,10 +492,7 @@ private fun OpponentHandView(player: Player, isActive: Boolean) {
|
|||||||
) {
|
) {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.size(8.dp).clip(RoundedCornerShape(4.dp)).background(MaterialTheme.colorScheme.primary)
|
||||||
.size(8.dp)
|
|
||||||
.clip(RoundedCornerShape(4.dp))
|
|
||||||
.background(MaterialTheme.colorScheme.primary)
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
}
|
}
|
||||||
@@ -339,18 +500,14 @@ private fun OpponentHandView(player: Player, isActive: Boolean) {
|
|||||||
text = player.name,
|
text = player.name,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
fontWeight = if (isActive) FontWeight.ExtraBold else FontWeight.Bold,
|
fontWeight = if (isActive) FontWeight.ExtraBold else FontWeight.Bold,
|
||||||
color = if (isActive) MaterialTheme.colorScheme.primary
|
color = if (isActive) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface
|
||||||
else MaterialTheme.colorScheme.onSurface
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Row {
|
Row {
|
||||||
repeat(minOf(player.hand.size, 5)) {
|
repeat(minOf(player.hand.size, 5)) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = true,
|
visible = true,
|
||||||
enter = scaleIn(
|
enter = scaleIn(initialScale = 0f, animationSpec = tween(200, delayMillis = it * 50))
|
||||||
initialScale = 0f,
|
|
||||||
animationSpec = tween(200, delayMillis = it * 50)
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
CardBack()
|
CardBack()
|
||||||
}
|
}
|
||||||
@@ -531,8 +688,7 @@ private fun PlayerHand(
|
|||||||
text = "${player.name} (${player.hand.size} Karten)",
|
text = "${player.name} (${player.hand.size} Karten)",
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = MaterialTheme.typography.titleMedium,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = if (isCurrentTurn) MaterialTheme.colorScheme.primary
|
color = if (isCurrentTurn) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface
|
||||||
else MaterialTheme.colorScheme.onSurface
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,8 +745,7 @@ private fun ActionButtons(
|
|||||||
enabled = isMyTurn && hasTwoCards && !(player?.hasCalledUno ?: true),
|
enabled = isMyTurn && hasTwoCards && !(player?.hasCalledUno ?: true),
|
||||||
modifier = Modifier.scale(unoScale),
|
modifier = Modifier.scale(unoScale),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = if (hasTwoCards) Color(0xFFFF6D00)
|
containerColor = if (hasTwoCards) Color(0xFFFF6D00) else MaterialTheme.colorScheme.primary
|
||||||
else MaterialTheme.colorScheme.primary
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text("UNO!")
|
Text("UNO!")
|
||||||
@@ -606,62 +761,35 @@ private fun ActionButtons(
|
|||||||
fun WinnerCelebration(winner: Player?, onDismiss: () -> Unit) {
|
fun WinnerCelebration(winner: Player?, onDismiss: () -> Unit) {
|
||||||
val infiniteTransition = rememberInfiniteTransition()
|
val infiniteTransition = rememberInfiniteTransition()
|
||||||
val celebrationScale by infiniteTransition.animateFloat(
|
val celebrationScale by infiniteTransition.animateFloat(
|
||||||
initialValue = 0.8f,
|
initialValue = 0.8f, targetValue = 1.1f,
|
||||||
targetValue = 1.1f,
|
animationSpec = infiniteRepeatable(tween(500, easing = FastOutSlowInEasing), RepeatMode.Reverse)
|
||||||
animationSpec = infiniteRepeatable(
|
|
||||||
animation = tween(500, easing = FastOutSlowInEasing),
|
|
||||||
repeatMode = RepeatMode.Reverse
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
val celebrationRotation by infiniteTransition.animateFloat(
|
val celebrationRotation by infiniteTransition.animateFloat(
|
||||||
initialValue = -3f,
|
initialValue = -3f, targetValue = 3f,
|
||||||
targetValue = 3f,
|
animationSpec = infiniteRepeatable(tween(400, easing = FastOutSlowInEasing), RepeatMode.Reverse)
|
||||||
animationSpec = infiniteRepeatable(
|
|
||||||
animation = tween(400, easing = FastOutSlowInEasing),
|
|
||||||
repeatMode = RepeatMode.Reverse
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = "🎉 Gewonnen! 🎉",
|
text = "Gewonnen!",
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth().graphicsLayer {
|
||||||
.fillMaxWidth()
|
scaleX = celebrationScale; scaleY = celebrationScale; rotationZ = celebrationRotation
|
||||||
.graphicsLayer {
|
},
|
||||||
scaleX = celebrationScale
|
textAlign = TextAlign.Center, fontSize = 28.sp, fontWeight = FontWeight.ExtraBold,
|
||||||
scaleY = celebrationScale
|
|
||||||
rotationZ = celebrationRotation
|
|
||||||
},
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
fontSize = 28.sp,
|
|
||||||
fontWeight = FontWeight.ExtraBold,
|
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
Column(
|
Column(modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
modifier = Modifier.fillMaxWidth(),
|
Text(winner?.name ?: "?", style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary)
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = winner?.name ?: "Unbekannt",
|
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
color = MaterialTheme.colorScheme.primary
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text("Herzlichen Glückwunsch!", style = MaterialTheme.typography.bodyLarge)
|
Text("Herzlichen Glückwunsch!", style = MaterialTheme.typography.bodyLarge)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
Button(
|
Button(onClick = onDismiss, modifier = Modifier.scale(celebrationScale)) { Text("Nochmal spielen") }
|
||||||
onClick = onDismiss,
|
|
||||||
modifier = Modifier.scale(celebrationScale)
|
|
||||||
) {
|
|
||||||
Text("Nochmal spielen")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -681,11 +809,8 @@ fun AnimatedColorPickerDialog(
|
|||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
title = {
|
title = {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(visible = visible, enter = slideInVertically(initialOffsetY = { -it / 2 }) + fadeIn()) {
|
||||||
visible = visible,
|
Text("Farbe wahlen")
|
||||||
enter = slideInVertically(initialOffsetY = { -it / 2 }) + fadeIn()
|
|
||||||
) {
|
|
||||||
Text("Farbe wählen")
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
@@ -701,27 +826,15 @@ fun AnimatedColorPickerDialog(
|
|||||||
CardColor.BLUE -> Color(0xFF1E88E5)
|
CardColor.BLUE -> Color(0xFF1E88E5)
|
||||||
CardColor.YELLOW -> Color(0xFFFDD835)
|
CardColor.YELLOW -> Color(0xFFFDD835)
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = visible,
|
visible = visible,
|
||||||
enter = scaleIn(
|
enter = scaleIn(initialScale = 0f, animationSpec = tween(300, delayMillis = index * 80, easing = FastOutSlowInEasing)) + fadeIn(tween(300, delayMillis = index * 80))
|
||||||
initialScale = 0f,
|
|
||||||
animationSpec = tween(300, delayMillis = index * 80, easing = FastOutSlowInEasing)
|
|
||||||
) + fadeIn(tween(300, delayMillis = index * 80))
|
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.size(60.dp).clip(RoundedCornerShape(8.dp)).background(bgColor).clickable { onColorSelected(color) },
|
||||||
.size(60.dp)
|
|
||||||
.clip(RoundedCornerShape(8.dp))
|
|
||||||
.background(bgColor)
|
|
||||||
.clickable { onColorSelected(color) },
|
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(color.displayName, color = if (color == CardColor.YELLOW) Color.Black else Color.White, fontWeight = FontWeight.Bold)
|
||||||
text = color.displayName,
|
|
||||||
color = if (color == CardColor.YELLOW) Color.Black else Color.White,
|
|
||||||
fontWeight = FontWeight.Bold
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user