react-native-waterfall-list-view 瀑布流组件+高性能+大数据+无限滚动

3,119 阅读4分钟

背景

瀑布流是一种流行的应用设计方式,特点是在垂直方向排列内容,而且每一行的列数可能不同,形成类似瀑布般的效果。瀑布流结构的优点有以下几点:

  1. 优化空间利用:瀑布流布局可充分利用屏幕空间,尤其是在多栏目显示有限基础上的互联网应用中。它能够有效填充各种尺寸的屏幕,使得页面内容布局更加美观。
  2. 提升用户体验:相比传统的分页式展示,瀑布流提供了无缝滚动体验,可以避免跳转和等待页面加载的不便,用户滚动浏览的过程中,新的内容会不断加载出来。
  3. 强化视觉冲击力:瀑布流布局多以图片为主,配合不规则的排版布局,可以强化视觉效果,使页面更加生动、丰富,有助于吸引并保留用户。
  4. 方便内容筛选:在瀑布流布局中,用户可以一眼扫过大量内容,便于进行快速筛选,有助于提升信息获取的效率。

采用瀑布流结构,有助于提升网站页面的美观度、易用性以及用户体验度,所以大家都喜欢这种方式来展示页面内容。

那么都有哪些公司在使用瀑布流呢?

抖音推荐页

ScreenRecording_09-19-2024 10-32-18_1.gif

快手发现页

ScreenRecording_09-19-2024 10-35-52_1.gif

小红书发现页

ScreenRecording_09-19-2024 10-37-32_1.gif

所以我也是基于react native的flatlist实现了一个瀑布流组件👏 喜欢的记得三连哦 感恩感谢🧣🥳🥳🥳 。

效果展示

两列瀑布流

RPReplay_Final1726644535.gif

三列瀑布流

RPReplay_Final1726645556.gif

使用说明

  • 组件基于flatlist实现  几乎支持flatlist所有属性 仅个别属性不支持 例如 horizontal 目前仅支持垂直方向
  • 基于ts + hooks实现 有较好的类型提示
  • 支持不定高item 内部通过布局自动计算 所以 getItemLayout 设置无效
  • 关于ref的支持 默认取到的是WaterFallList的ref  内部包括自定义的属性和flatlistRef.   如果想获取内部flatlist的ref对象 可以通过WaterFallList内部转发的的 flatListRef 对象
<WaterFallList
    ref={waterfallRef}
    ItemSeparatorComponent={() => <View />}
    initialNumToRender={10}
    windowSize={10}
    onScroll={onScroll}
    renderItem={({ item }) => <Item data={item}></Item>}
    data={list}
    contentContainerStyle={{ flexGrow: 1 }}
    onEndReachedThreshold={0.5}
    onEndReached={onEndReached}
    numColumns={2}
    showsVerticalScrollIndicator={false}
    ListEmptyComponent={() => <View />}
    ListFooterComponent={() => <View />}
/>;

注意事项

  1. item最大高度与最小高度差值不宜过大 建议:  最小高度>=最大高度的30%
  2. item渲染完成后 不建议动态改变item的高度 会引起布局抖动
  3. 内部封装了refreshList函数 在刷新列表前 建议先调用此函数(刷新调用即可 列表项增加不需要调用)
  4. 仅支持垂直瀑布流
  5. 因为 rn 官方点击组件在 Android 上超出父容器无法点击的问题,组件内部的触摸组件需要使用 react-native-gesture-handler 中的替换 rn 官方组件
import {
  TouchableNativeFeedback,
  TouchableHighlight,
  TouchableOpacity,
  TouchableWithoutFeedback,
} from "react-native";

// has to be replaced with:
import {
  TouchableNativeFeedback,
  TouchableHighlight,
  TouchableOpacity,
  TouchableWithoutFeedback,
} from "react-native-gesture-handler";

原理

截屏2024-09-18 20.12.59.png

  1. 首先更改数据源 将单列表数组转换为N维数组确定每行的具体item数
  2. 第一次渲染 获取到每个元素的真实高度信息(获取定位信息的方式可以参考这篇文章),并通过_itemHeightsRef记录下来。
  3. 当高度信息收集完成 触发强制刷新 再次渲染一次列表
  4. 决策当前元素应该放在第几列 每行的高度是多少 当前元素距离容器顶部间距是多少  当前行距离容器顶部间距是多少

例如当前一行是这个形式: 截屏2024-09-18 19.21.35.png

第三个元素应该加在下一行的最短一列: 截屏2024-09-18 19.22.03.png

同理第四个元素也加在最短的一列 第二列: 截屏2024-09-18 19.26.49.png

然后计算第二行的行高:
因为flatlist的一行是以最长的元素高度为准 所以我们需要计算出最长的元素高度是多少 并且还要减去上一行的高度这个偏移量。 所以高度如下
截屏2024-09-18 19.28.32.png 然后不断循环列表 直到结束。

github源码

react-native-waterfall-list-view

其他组件