Implement Material 3 Expressive

Signed-off-by: denis0001-dev <denis0001.dev@ya.ru>
This commit is contained in:
2026-03-20 17:11:59 +03:00
Unverified
parent fedfa117d7
commit ecffdb9048
@@ -3,9 +3,7 @@ package ru.fromchat.ui.chat
import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
@@ -31,10 +29,12 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AttachFile import androidx.compose.material.icons.filled.AttachFile
import androidx.compose.material.icons.rounded.Download import androidx.compose.material.icons.rounded.Download
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.CircularWavyProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.WavyProgressIndicatorDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@@ -350,43 +350,44 @@ private fun ExpressiveUploadIndicator(
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val clampedProgress = uploadProgress?.coerceIn(0, 100) val clampedProgress = uploadProgress?.coerceIn(0, 100)
val animatedProgress by animateFloatAsState( val indeterminate = clampedProgress == null || clampedProgress == 0
targetValue = (clampedProgress ?: 0) / 100f, val waveActive = clampedProgress != null && clampedProgress in 1..99
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy, val waveAnimSpec = tween<Float>(durationMillis = 320, easing = FastOutSlowInEasing)
stiffness = Spring.StiffnessVeryLow,
visibilityThreshold = 1 / 1000f val targetWaveStrength = if (waveActive) 1f else 0f
), val animatedWaveStrength by animateFloatAsState(
label = "uploadProgress" targetValue = targetWaveStrength,
animationSpec = waveAnimSpec,
label = "waveStrength"
) )
Box( val animatedProgress by animateFloatAsState(
modifier = Modifier targetValue = (clampedProgress ?: 0) / 100f,
.clip(RoundedCornerShape(20.dp)) animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
.background(MaterialTheme.colorScheme.surface.copy(alpha = 0.82f)) label = "uploadProgress"
.padding(horizontal = 14.dp, vertical = 10.dp) )
) { val primary = MaterialTheme.colorScheme.primary
Column( val trackColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.28f)
horizontalAlignment = Alignment.CenterHorizontally, val defaultIndicatorAmplitude = WavyProgressIndicatorDefaults.indicatorAmplitude
verticalArrangement = Arrangement.spacedBy(8.dp) val ringModifier = Modifier.size(56.dp)
) {
if (clampedProgress != null) { Box(modifier = modifier, contentAlignment = Alignment.Center) {
LoadingIndicator( if (indeterminate) {
progress = { animatedProgress }, CircularWavyProgressIndicator(
modifier = modifier, modifier = ringModifier,
color = MaterialTheme.colorScheme.primary color = primary,
) trackColor = trackColor,
Text( amplitude = animatedWaveStrength
text = "$clampedProgress%", )
style = MaterialTheme.typography.labelMedium, } else {
color = MaterialTheme.colorScheme.onSurface CircularWavyProgressIndicator(
) progress = { animatedProgress },
} else { modifier = ringModifier,
LoadingIndicator( color = primary,
modifier = modifier, trackColor = trackColor,
color = MaterialTheme.colorScheme.primary amplitude = { p -> animatedWaveStrength * defaultIndicatorAmplitude(p) }
) )
}
} }
} }
} }