feat: Enhance emoji picker animation with smooth slide-up effect and visibility control
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user