feat: tweak slide to reply animation

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2025-04-11 18:37:16 +02:00
parent c211f24e5e
commit 4acc42294c
1 changed files with 41 additions and 48 deletions

View File

@ -4,8 +4,9 @@ import android.annotation.SuppressLint
import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.slideInVertically import androidx.compose.animation.core.spring
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@ -218,54 +219,45 @@ fun RegularMessage(
with(LocalDensity.current) { with(LocalDensity.current) {
val msgHeightAsDp = messageHeight.toDp() val msgHeightAsDp = messageHeight.toDp()
BoxWithConstraints(Modifier.height(msgHeightAsDp)) { BoxWithConstraints(Modifier.height(msgHeightAsDp)) {
AnimatedContent( Row(
targetState = canReleaseToSend, Modifier
transitionSpec = { .height(msgHeightAsDp)
if (canReleaseToSend) { .requiredHeightIn(max = msgHeightAsDp) // must not cause message to be taller
slideInVertically { -it } togetherWith slideOutVertically { it } .offset(
} else { x = with(LocalDensity.current) {
slideInVertically { it } togetherWith slideOutVertically { -it } maxWidth - abs(
} animOffsetX
}, ).toDp()
label = "Swipe to Reply indicator content slide" }
)
.background(indicatorBackground)
.fillMaxWidth()
.padding(start = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(
8.dp,
Alignment.Start
)
) { ) {
Row( Icon(
Modifier painter = painterResource(R.drawable.ic_reply_24dp),
.height(msgHeightAsDp) contentDescription = null,
.requiredHeightIn(max = msgHeightAsDp) // must not cause message to be taller modifier = Modifier.size(
.offset( min(
x = with(LocalDensity.current) { msgHeightAsDp - 4.dp,
maxWidth - abs( 24.dp
animOffsetX
).toDp()
}
) )
.background( ),
// indicatorBackground tint = indicatorForeground
if (it) MaterialTheme.colorScheme.inversePrimary )
else MaterialTheme.colorScheme.primaryContainer AnimatedContent(
) targetState = canReleaseToSend,
.fillMaxWidth() transitionSpec = {
.padding(start = 16.dp), fadeIn(animationSpec = spring()) togetherWith
verticalAlignment = Alignment.CenterVertically, fadeOut(animationSpec = spring())
horizontalArrangement = Arrangement.spacedBy( },
8.dp, label = "Swipe to Reply indicator label"
Alignment.Start
)
) { ) {
Icon(
painter = painterResource(R.drawable.ic_reply_24dp),
contentDescription = null,
modifier = Modifier.size(
min(
msgHeightAsDp - 4.dp,
24.dp
)
),
tint = // indicatorForeground
if (it) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.onPrimaryContainer
)
Text( Text(
when (it) { when (it) {
true -> stringResource( true -> stringResource(
@ -276,7 +268,8 @@ fun RegularMessage(
R.string.swipe_to_reply_keep_swiping R.string.swipe_to_reply_keep_swiping
) )
}, },
color = indicatorForeground color = indicatorForeground,
modifier = Modifier.fillMaxWidth()
) )
} }
} }