feat: Enhance emoji picker animation with smooth slide-up effect and visibility control

This commit is contained in:
k1ngsterr1
2026-01-14 02:32:33 +05:00
parent ee543ddf18
commit 8c5efae0a1

View File

@@ -1039,17 +1039,13 @@ fun ChatDetailScreen(
}
}
) { paddingValues ->
// 🔥 Дополнительный отступ снизу для эмодзи панели
// Учитываем высоту панели + 16dp отступ снизу для безопасной зоны
val emojiBottomPadding = if (showEmojiPicker && imeHeight < 50.dp) (emojiPanelHeight + 16.dp) else 0.dp
// 🔥 Column структура - список сжимается когда клавиатура/эмодзи открывается
// 🔥 Column структура - список сжимается когда клавиатура открывается
// Emoji panel внутри MessageInputBar - НЕ нужен дополнительный отступ
Column(
modifier = Modifier
.fillMaxSize()
.padding(top = paddingValues.calculateTopPadding())
.imePadding() // 🔥 Поднимаем весь контент над клавиатурой
.padding(bottom = emojiBottomPadding) // 🔥 Отступ для эмодзи панели (после imePadding!)
.background(backgroundColor)
) {
// Список сообщений - занимает всё доступное место
@@ -2021,9 +2017,12 @@ private fun MessageInputBar(
// Состояние отправки - можно отправить если есть текст ИЛИ есть reply
val canSend = remember(value, hasReply) { value.isNotBlank() || hasReply }
// 🔥 Закрываем эмодзи панель когда клавиатура открывается
// 🔥 Плавно закрываем эмодзи панель когда клавиатура ПОЛНОСТЬЮ открылась
// Используем LaunchedEffect с debounce чтобы избежать дёрганья
LaunchedEffect(isKeyboardVisible) {
if (isKeyboardVisible && showEmojiPicker) {
// Ждём пока клавиатура полностью поднимется (200ms)
kotlinx.coroutines.delay(200)
onToggleEmojiPicker(false)
}
}
@@ -2049,14 +2048,18 @@ private fun MessageInputBar(
if (showEmojiPicker) {
// Закрываем emoji picker и открываем клавиатуру
onToggleEmojiPicker(false)
// Клавиатура откроется автоматически т.к. фокус остался
// Открываем клавиатуру
editTextView?.let { editText ->
editText.requestFocus()
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT)
}
} else {
// Закрываем клавиатуру через IMM
// 🔥 Сначала показываем эмодзи панель
onToggleEmojiPicker(true)
// Потом скрываем клавиатуру (панель уже видна, поэтому не будет прыжка)
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
// 🔥 Показываем эмодзи сразу - без задержки!
onToggleEmojiPicker(true)
android.util.Log.d("MessageInputBar", "🎯 toggleEmojiPicker: showEmojiPicker=true, emojiPanelHeight=$emojiPanelHeight")
}
}
@@ -2298,46 +2301,40 @@ private fun MessageInputBar(
} // End of else (not blocked)
// 🔥 APPLE EMOJI PICKER - БЕЗ анимации когда клавиатура открывается
// 🔥 APPLE EMOJI PICKER - плавная анимация slide up
if (!isBlocked) {
// Высота панели: 0 если клавиатура видна или эмодзи закрыты, иначе emojiPanelHeight
val targetHeight = if (isKeyboardVisible || !showEmojiPicker) 0.dp else emojiPanelHeight
// Показываем только когда клавиатура закрыта И эмодзи открыты
val showPanel = showEmojiPicker && !isKeyboardVisible
// Анимируем только когда клавиатура закрыта
val animatedHeight by animateDpAsState(
targetValue = targetHeight,
animationSpec = if (isKeyboardVisible) {
// Мгновенно когда клавиатура открывается
snap()
} else {
// Быстрая анимация (200ms)
tween(durationMillis = 200, easing = FastOutSlowInEasing)
},
label = "EmojiPanelHeight"
)
// 🔥 Показываем Box только когда есть высота (НЕ занимает место когда скрыт!)
if (animatedHeight > 0.dp) {
AnimatedVisibility(
visible = showPanel,
enter = slideInVertically(
initialOffsetY = { it }, // Снизу вверх
animationSpec = tween(200, easing = FastOutSlowInEasing)
),
exit = slideOutVertically(
targetOffsetY = { it }, // Сверху вниз
animationSpec = tween(150, easing = FastOutSlowInEasing)
)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(animatedHeight)
.height(emojiPanelHeight)
.padding(bottom = 16.dp)
) {
if (showEmojiPicker) {
AppleEmojiPickerPanel(
isDarkTheme = isDarkTheme,
onEmojiSelected = { emoji ->
onValueChange(value + emoji)
},
onClose = {
onToggleEmojiPicker(false)
},
modifier = Modifier
.fillMaxWidth()
.height(emojiPanelHeight - 16.dp)
)
}
AppleEmojiPickerPanel(
isDarkTheme = isDarkTheme,
onEmojiSelected = { emoji ->
onValueChange(value + emoji)
},
onClose = {
onToggleEmojiPicker(false)
},
modifier = Modifier
.fillMaxWidth()
.height(emojiPanelHeight - 16.dp)
)
}
}
} // End of if (!isBlocked) for emoji picker