AI对话(SSE)界面ScrollView的自滚动
应用场景描述
在很多当下的AI聊天应用中,AI的回复都采取了「打字机」效果的呈现。这种方式能够防止用户等待的时间过长,从而提升体验。
而这种「打字机」效果的实现,实际上是依赖了HTTP的实时推送技术:SSE(Server-Sent Event),即「服务端发送事件」。
技术难点描述
尽管自己平时在使用这种功能的时候,没有去深究这种功能实现的技术细节;但当自己实际着手去实现这么一个功能的时候,却发现有一个非常核心的问题:如何时刻都展现前端接收到的SSE最新内容?
详细来说,如果没有做任何额外的改动,那么随着接收内容的增长,消息气泡会不断变长,最终超出手机屏幕的可视范围。
当然,在ScrollView的contentContainerStyle是flexGrow:1的情况下,只要通过滑动屏幕,还是能看到消息气泡的下半部分的,因为ScrollView在这种情况下会随着子组件内容的增长而变长。
但是,这种交互模式的问题就在于:当AI回复的文本内容过长时,用户需要手动滑动屏幕才能看到最新的内容;这也不是目前主流的AI应用中所呈现的模式。
我的尝试
一开始,我先是求助了React Native的API文档,得知可以通过使用一个ScrollView的ref,来调用其scrollToEnd()的方法。
而为了实现能够时刻展示最新回复内容的功能,我就尝试在每次更新消息的时候,都调用一次scrollToEnd()
es.onmessage = (e) => {
// 省略其它代码
scrollViewRef.current?.scrollToEnd();
};
但是,这种实现方法实际给我带来的效果并不是我想要的。尽管视图可以进行自动滚动,但是在某些时候,SSE回复的最新内容还是会被遮挡。并且动画效果也是十分的奇怪。
解决方案
在网上的论坛和AI之间挣扎了很久之后,我终于在腾讯云|开发者社区(其实是Stack Overflow的一个用户提问)里一个帖子中,找到了解决了这个问题的完美方案:
也就是说,通过在ScrollView的onContentSizeChange()方法中进行监听;只要ScrollView的大小变了,就在ref上调用scrollToEnd()方法。
在自己的代码中采纳了这种方法之后,我发现这完美地符合了我对该功能的预期。
总结
希望这篇博客能够帮到遇到类似问题的开发者,减少你们在寻找这个问题解决方案上花的时间。