聊天界面键盘底部Padding动画

This commit is contained in:
2024-09-24 04:45:55 +08:00
parent b94d8fb7b3
commit c21ef36ecb

View File

@@ -1,10 +1,13 @@
package com.aiosman.riderpro.ui.chat package com.aiosman.riderpro.ui.chat
import android.view.KeyEvent
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -14,6 +17,7 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
@@ -23,6 +27,8 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Scaffold import androidx.compose.material.Scaffold
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -37,11 +43,19 @@ import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.SoftwareKeyboardController
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -52,6 +66,7 @@ import com.aiosman.riderpro.R
import com.aiosman.riderpro.ui.composables.CustomAsyncImage import com.aiosman.riderpro.ui.composables.CustomAsyncImage
import com.aiosman.riderpro.ui.composables.StatusBarSpacer import com.aiosman.riderpro.ui.composables.StatusBarSpacer
import com.aiosman.riderpro.ui.modifiers.noRippleClickable import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -146,11 +161,6 @@ fun ChatScreen(userId: String) {
ChatInput() { ChatInput() {
viewModel.sendMessage(it, context) viewModel.sendMessage(it, context)
} }
Box(
modifier = Modifier
.fillMaxWidth()
.height(navigationBarHeight)
)
} }
} }
) { paddingValues -> ) { paddingValues ->
@@ -320,20 +330,46 @@ fun ChatItem(item: ChatItem, currentUserId: String) {
fun ChatInput( fun ChatInput(
onSend: (String) -> Unit = {} onSend: (String) -> Unit = {}
) { ) {
val navigationBarHeight = with(LocalDensity.current) {
WindowInsets.navigationBars.getBottom(this).toDp()
}
var keyboardController by remember { mutableStateOf<SoftwareKeyboardController?>(null) }
var isKeyboardOpen by remember { mutableStateOf(false) }
var text by remember { mutableStateOf("") } var text by remember { mutableStateOf("") }
val inputBarHeight by animateDpAsState(
targetValue = if (isKeyboardOpen) 8.dp else navigationBarHeight,
animationSpec = tween(durationMillis = 300), label = ""
)
// 在 isKeyboardOpen 变化时立即更新 inputBarHeight 的动画目标值
LaunchedEffect(isKeyboardOpen) {
inputBarHeight // 触发 inputBarHeight 的重组
}
val focusManager = LocalFocusManager.current
val windowInsets = WindowInsets.ime
val density = LocalDensity.current
val softwareKeyboardController = LocalSoftwareKeyboardController.current
val currentDensity by rememberUpdatedState(density)
LaunchedEffect(windowInsets.getBottom(currentDensity)) {
if (windowInsets.getBottom(currentDensity) <= 0) {
focusManager.clearFocus()
}
}
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp, horizontal = 16.dp) .padding(horizontal = 16.dp)
.padding(bottom = inputBarHeight)
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.clip(androidx.compose.foundation.shape.RoundedCornerShape(16.dp)) .clip(RoundedCornerShape(16.dp))
.background(Color(0xffe5e5e5)) .background(Color(0xffe5e5e5))
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
contentAlignment = androidx.compose.ui.Alignment.CenterStart contentAlignment = androidx.compose.ui.Alignment.CenterStart
) { ) {
BasicTextField( BasicTextField(
value = text, value = text,
@@ -347,7 +383,23 @@ fun ChatInput(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp) .padding(vertical = 8.dp)
.onFocusChanged { focusState ->
isKeyboardOpen = focusState.isFocused
}
.pointerInput(Unit) {
awaitPointerEventScope {
keyboardController = softwareKeyboardController
awaitFirstDown().also {
keyboardController?.show()
}
}
},
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(
onDone = {
keyboardController?.hide()
}
)
) )
} }
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))