feat: Optimize chat screen transitions by removing redundant animations for a smoother user experience

This commit is contained in:
k1ngsterr1
2026-01-13 18:36:17 +05:00
parent 435c07bf01
commit 4881024a9c
5 changed files with 128 additions and 111 deletions

View File

@@ -6,6 +6,9 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.*
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.FastOutLinearInEasing
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
@@ -234,7 +237,7 @@ fun MainScreen(
var selectedUser by remember { mutableStateOf<SearchUser?>(null) }
var showSearchScreen by remember { mutableStateOf(false) }
// Анимированный переход между экранами - Telegram-style
// 🔥 TELEGRAM-STYLE анимация - чистый slide БЕЗ прозрачности
AnimatedContent(
targetState = Triple(selectedUser, showSearchScreen, Unit),
transitionSpec = {
@@ -244,113 +247,79 @@ fun MainScreen(
val isExitingSearch = !targetState.second && initialState.second
when {
// 🚀 Вход в чат - slide справа + fade (как Telegram)
// 🚀 Вход в чат - чистый slide справа (как Telegram/iOS)
// Новый экран полностью покрывает старый, никакой прозрачности
isEnteringChat -> {
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth / 3 }, // Начинаем на 1/3 экрана справа
animationSpec = tween(
durationMillis = 250,
easing = FastOutSlowInEasing
)
) + fadeIn(
initialAlpha = 0.3f,
animationSpec = tween(
durationMillis = 200,
easing = FastOutSlowInEasing
initialOffsetX = { fullWidth -> fullWidth }, // Начинаем за экраном справа
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMediumLow // Плавно но быстро
)
) togetherWith slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth / 6 }, // Список уходит немного влево
animationSpec = tween(
durationMillis = 250,
easing = FastOutSlowInEasing
)
) + fadeOut(
targetAlpha = 0.5f,
animationSpec = tween(
durationMillis = 200,
easing = FastOutSlowInEasing
targetOffsetX = { fullWidth -> -fullWidth / 4 }, // Старый экран уходит влево на 25%
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
}
// 🔙 Выход из чата - slide вправо + fade (быстрее)
// 🔙 Выход из чата - обратный slide
isExitingChat -> {
slideInHorizontally(
initialOffsetX = { fullWidth -> -fullWidth / 6 }, // Список возвращается слева
animationSpec = tween(
durationMillis = 200,
easing = FastOutSlowInEasing
)
) + fadeIn(
initialAlpha = 0.5f,
animationSpec = tween(
durationMillis = 180,
easing = FastOutSlowInEasing
initialOffsetX = { fullWidth -> -fullWidth / 4 }, // Список возвращается слева
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMedium // Чуть быстрее при выходе
)
) togetherWith slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth / 2 }, // Чат уходит вправо
animationSpec = tween(
durationMillis = 200,
easing = FastOutSlowInEasing
)
) + fadeOut(
animationSpec = tween(
durationMillis = 180,
easing = FastOutSlowInEasing
targetOffsetX = { fullWidth -> fullWidth }, // Чат уходит за экран вправо
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMedium
)
)
}
// 🔍 Вход в поиск - slide снизу
// 🔍 Вход в поиск - slide сверху
isEnteringSearch -> {
slideInVertically(
initialOffsetY = { fullHeight -> fullHeight / 4 },
animationSpec = tween(
durationMillis = 220,
easing = FastOutSlowInEasing
)
) + fadeIn(
animationSpec = tween(
durationMillis = 200,
easing = FastOutSlowInEasing
)
) togetherWith fadeOut(
animationSpec = tween(
durationMillis = 150,
easing = FastOutSlowInEasing
)
)
}
// ❌ Выход из поиска - slide вниз
isExitingSearch -> {
fadeIn(
animationSpec = tween(
durationMillis = 180,
easing = FastOutSlowInEasing
initialOffsetY = { -it },
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMediumLow
)
) togetherWith slideOutVertically(
targetOffsetY = { fullHeight -> fullHeight / 4 },
animationSpec = tween(
durationMillis = 200,
easing = FastOutSlowInEasing
)
) + fadeOut(
animationSpec = tween(
durationMillis = 150,
easing = FastOutSlowInEasing
targetOffsetY = { it / 4 },
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
}
// Default fade
else -> {
fadeIn(
animationSpec = tween(durationMillis = 200)
) togetherWith fadeOut(
animationSpec = tween(durationMillis = 150)
// ❌ Выход из поиска
isExitingSearch -> {
slideInVertically(
initialOffsetY = { it / 4 },
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMedium
)
) togetherWith slideOutVertically(
targetOffsetY = { -it },
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMedium
)
)
}
// Default - мгновенный переход
else -> {
EnterTransition.None togetherWith ExitTransition.None
}
}
},
label = "screenNavigation"