React Native:如何构建双向无限滚动
👋 简介
在FlatList或SectionList之上,关于使用 React Native 实现无限滚动,在 Stack Overflow 和 GitHub 上进行了很多讨论。我发现对于双向无限滚动没有任何简单的解决方案,它适用于 Android 和IOS。最近,在处理React Native Chat SDKatStream的v3.0.0时,我们为我们的聊天组件添加了双向无限滚动。我们必须克服许多障碍才能实现这一目标,同时保持良好的滚动用户体验(尤其是对于 Android)。因此,我们决定在FlatList之上发布一个优秀的小型开源包,以使其他 React Native 开发人员更容易完成这项任务。
GitHub⭐:github.com/getstream/react-native-bidirectional-infinite-scroll
🔌 用法
如前所述,这个包是 FlatList 的包装器,因此它可以像 React Native 中的 FlatList 一样使用,只需要很少的额外属性:
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--lih8GnB5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads .s3.amazonaws.com/uploads/articles/euj48dje72sea9ps3nn3.png)
🔮 快速预览
进一步向下滚动,查看教程
iOS
安卓


让我们深入
-
什么和如何?
-
教程:双向无限滚动聊天 UI
-
还有什么?!
📚 什么和如何
本节将带您了解实现双向无限滚动的障碍以及我们如何解决这些障碍。
支持onStartReached
FlatList 来自 React Native 的内置支持单向无限滚动(从列表末尾开始)。您可以在FlatList上添加一个道具onEndReached。当您的滚动条接近列表末尾时,将调用此函数,因此您可以通过此函数将更多项目附加到列表中。你可以在谷歌上搜索 React Native 无限滚动,你会发现很多这样的例子。不幸的是,FlatList没有为onStartReached提供任何类似的道具,用于在其他方向无限滚动。
我们通过简单地在FlatList上添加onScroll处理程序,并在滚动接近列表开头时执行回调函数 (onStartReached) 来添加对此道具的支持作为此包的一部分。如果你看一下VirtualizedList的实现,你会注意到onEndReachedfunction 每个内容长度只被调用一次。这是为了一个好的目的 - 避免在每次滚动位置更改时调用冗余函数。在这个包中已经对onStartReached进行了类似的优化。
onStartReached和onEndReached之间的竞争条件
为了保持流畅的滚动体验,我们需要管理onStartReached和onEndReached的执行顺序。因为如果两个回调(几乎)同时发生,这意味着项目将从两个方向添加到列表中。这可能会导致滚动跳转,这不是一个好的用户体验。因此,必须确保一个回调等待另一个回调完成。
onStartReachedThreshold和onEndReachedThreshold
来自 React Native 的FlatList支持道具onEndReachedThreshold,即此处记录的
列表的底部边缘距离内容的末尾有多远(以列表的可见长度为单位)才能触发
onEndReached回调。
相反,使用固定值偏移量(距列表末尾的距离)更容易触发这些回调之一。因此,我们可以在我们的实现中维护这两个值。因此onStartReachedThreshold和onEndReachedThreshold道具接受数字 - 距列表末尾的距离以触发这些回调之一。
流畅的滚动体验
来自 React Native 的FlatList接受一个道具 -maintainVisibleContentPosition,这可以确保当更多项目添加到列表中时,您的滚动不会跳到列表的末尾。但是这个道具目前只在 iOS 上支持。因此,从这个PR中获得一些灵感,我们发布了我们的单独包以在 Android-flat-list-mvcp上添加对这个道具的支持。因此@stream-io/flat-list-mvcp是react-native-bidirectional-scroll包的依赖项。
🖥 教程:双向无限滚动聊天 UI
现在让我们看看如何实现一个聊天消息列表,在两个方向上无限滚动。
设置
让我们从创建一个 React Native 应用开始:
$ npx react-native init AwesomeChatList
$ cd AwesomeChatList
进入全屏模式 退出全屏模式
添加所需的依赖项:
$ yarn add react-native-bidirectional-infinite-scroll @stream-io/flat-list-mvcp
进入全屏模式 退出全屏模式
接下来,运行应用程序:
$ npx react-native run-ios
进入全屏模式 退出全屏模式
注意:当您更改代码时,服务器将自动刷新。
创建消息列表
在某个编辑器中打开这个项目(我喜欢 VS Code)并在项目的根目录中打开App.js。
我们将使用虚拟消息填充列表。在实际应用程序中,这些消息是针对服务器查询的。例如,我们可以编写一个简单的实用程序函数来模拟这个 API 调用来查询n条消息。
创建文件 -utils.js
接下来,让我们为消息气泡编写一个小的 UI 组件。创建一个名为MessageBubble.js的文件。
现在让我们首先实现一个简单的列表,它会在第一次加载时呈现这些消息。将以下内容复制到App.js并点击保存。
您应该能够看到如右侧屏幕截图所示的消息列表。
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--_fGIftrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://stream-blog- v2.imgix.net/blog/wp-content/uploads/546da9ee13625ce4f5ebba16747e50a0/0coucxr19ywzwftsicgq.png)
添加无限滚动
接下来,让我们通过添加onStartReached和onEndReached两个 prop 函数来实现无限滚动到列表。
-
onStartReached- 在列表开头添加 10 条消息 -
onEndReached- 在列表末尾添加 10 条消息
将App.js的内容替换为以下内容:
就是这样。如果您向上或向下滚动,您将看到列表中加载了新消息,并且滚动位置也保持不变(适用于 Android 和 iOS)
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--Ig6jTu7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://stream-blog -v2.imgix.net/blog/wp-content/uploads/c6394ba8863774747d8bb552e28200ad/dvg7qhro5044qfvqn3v8.gif)
发信息
在真正的聊天应用程序中,您实际上并没有“无限”滚动。loadMoreRecentMessages功能总是有尽头的。在此之后,当其他用户发送新消息或您发送新消息时,您将希望滚动条自动移动到列表底部。
基本上,在这一点之后,我们希望启用FlatList的“自动滚动到顶部”(在我们的例子中是底部,因为列表是倒置的)功能。您可以通过将道具enableAutoscrollToTop设置为true来实现。此外,您还可以设置autoscrollToTopThreshold至true。
-
让我们尝试通过保持最近消息被查询次数的计数器来模拟这种情况。一旦计数器超过 2,让我们停止查询消息。
-
让我们在底部添加一个“发送消息”按钮来发送一条消息。
将App.js的内容替换为以下内容
现在滚动到底部几次,直到您无法加载任何最近的消息。现在尝试按“发送消息”按钮发送一条消息。您将看到滚动自动滚动到列表底部。但是,如果您向上滚动一点然后发送消息 - 那么滚动位置将保持不变。autoscrollToTopThreshold属性控制这个阈值。
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--uLyvjcMd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/3wdzvxpcdabfeuv98nvn.gif)
🎉 恭喜!!更重要的是?!
你已经使用 React Native 实现了双向无限滚动!此外,以下道具可用于添加更多自定义:
-
activityIndicatorColor -
enableAutoscrollToTop -
autoscrollToTopThreshold -
onStartReachedThreshold -
onEndReachedThreshold -
showDefaultLoadingIndicators -
HeaderLoadingIndicator -
FooterLoadingIndicator
希望你觉得它有用。随时在此处添加一些问题、评论和反馈。并且不要忘记在github repo上放一个⭐。编码快乐!!
更多推荐


所有评论(0)