fix(chat): 新消息自动跟随底部(微信/QQ 式)
reverseLayout 会锚定原可见项,导致新消息插到视口外。改为:滚动结束时记录是否贴底(容差 64px),最新一项变化且处于跟随状态时 animateScrollToItem(0);用户上滑查看历史时不再强制滚动。
This commit is contained in:
1 parent
67ed0479e4
commit
e04995a84d
1 file changed
+28
@@ -18,6 +18,9 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -40,6 +43,9 @@ import top.yukonga.miuix.kmp.icon.MiuixIcons
|
||||
import top.yukonga.miuix.kmp.icon.basic.Sidebar
|
||||
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||
|
||||
/** 判定「贴着底部」的容差(px)。 */
|
||||
private const val BOTTOM_TOLERANCE = 64
|
||||
|
||||
@Composable
|
||||
fun ChatScreen(
|
||||
container: AppContainer,
|
||||
@@ -52,6 +58,28 @@ fun ChatScreen(
|
||||
val state by viewModel.state.collectAsState()
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
// 是否跟随底部(微信/QQ 式):只有用户主动滚到别处时才停止跟随。
|
||||
// 只在「滚动结束」时更新,避免新消息插入导致的锚点位移把状态带偏。
|
||||
var followBottom by remember { mutableStateOf(true) }
|
||||
LaunchedEffect(listState) {
|
||||
snapshotFlow { listState.isScrollInProgress }
|
||||
.distinctUntilChanged()
|
||||
.collect { scrolling ->
|
||||
if (!scrolling) {
|
||||
followBottom = listState.firstVisibleItemIndex == 0 &&
|
||||
listState.firstVisibleItemScrollOffset < BOTTOM_TOLERANCE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 最新一项变化(新消息 / 乐观气泡 / 流式气泡 / 落库归一)时,跟随则滚到底。
|
||||
val newestKey = state.items.lastOrNull()?.key
|
||||
LaunchedEffect(newestKey) {
|
||||
if (newestKey != null && followBottom) {
|
||||
listState.animateScrollToItem(0)
|
||||
}
|
||||
}
|
||||
|
||||
// reverseLayout 下「列表末尾」就是屏幕顶部;接近末尾时加载更早的一页。
|
||||
LaunchedEffect(listState) {
|
||||
snapshotFlow {
|
||||
|
||||
Reference in new issue
Block a user