2021SC@SDUSC
在上一篇blog中我们对Hippy-react中的image和list-view组件进行了分析,本次我们继续进行WaterfallView组件的分析。
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。
一、首先我们来看该组件中的参数和方法列表;
参数 | 作用 |
---|---|
numberOfColumns | 瀑布流中列的数量 |
numberOfItems | 瀑布流中的item数量 |
contentInset | 内容缩进 |
columnSpacing | 列之间的距离 |
interItemSpacing | item之间的垂直距离 |
preloadItemNumber | 到达list末尾时要预先加载的item数量 |
containPullHeader | 判断是否包含PullHeader组件 |
containPullFooter | 判断是否包含Pullfooter组件 |
containBannerView | 判断是否存在Banner视图 |
renderItem | 传递数据并返回行组件。方法入参是当前 item 的 index,在这里可以凭借 index 获取到瀑布流一个具体单元格的数据,从而决定如何渲染这个单元格 |
renderBanner?() | banner的渲染方式 |
renderPullHeader?() | pullHeader的渲染方式 |
renderPullFooter?() | pullFooter的渲染方式 |
getItemType?(index: number) | 指定一个函数,在其中返回对应条目的类型,List 将对同类型条目进行复用,合理的类型拆分可以很好地提升list 性能 |
getItemStyle?(index: number) | 设置WaterfallItem容器样式 |
getItemKey?(index: number) | 指定一个函数,在其中返回对应条目的 Key 值 |
onEndReached?() | 在所有的数据都已经渲染过,并且列表被滚动到最后一条时被调用 |
onItemLayout?(evt: LayoutEvent, index: number): void | 在第一次布局或者布局改变时被调用 |
onScroll | 在触发waterFall的滑动事件时被调用 |
onHeaderPulling? (): void; | 当用户下拉 ListView 时调用 |
onHeaderReleased? (): void; | 当用户释放拉取 WaterfallView 时调用 |
onFooterPulling? (): void; | 当用户向上滑动 WaterfallView 以获取更多数据时调用 |
onFooterReleased? (): void; | 当用户释放获取更多数据时调用 |
onInitialListReady? (): void; | 在waterFall准备好时被调用 |
以上就是WaterFallView组件中的参数及函数情况,我们在进行开发时可以对照以上作用描述以便使用。
二、WaterfallView类的实现
1.其中关于滚动方法的实现:其中onScroll在触发滑动时被调用,scrollToIndex决定Waterfall滑动到第几个item,scrollToContentOffset控制的是具体滑动的坐标,二者都需要调用callUIFunction进行操作。
关于onScroll,我们先来看其声明代码:
onScroll?(evt: {
startEdgePos: number,
endEdgePos: number,
firstVisibleRowIndex: number,
lastVisibleRowIndex: number,
visibleRowFrames: Object
}): void;
其中
startEdgePos表示距离 List 顶部边缘滚动偏移量;
endEdgePos表示距离 List 底部边缘滚动偏移量;
firstVisibleRowIndex表示当前可见区域内第一个元素的索引;
lastVisibleRowIndex表示当前可见区域内最后一个元素的索引;
visibleRowFrames表示当前可见区域内所有 item 的信息(x,y,width,height)
关于scrollToIndex以及scrollToContentOffset的代码如下:
public scrollToIndex({ index = 0, animated = true }) {
callUIFunction(this.instance as Fiber, 'scrollToIndex', [index, index, animated]);
}
public scrollToContentOffset({
xOffset = 0,
yOffset = 0,
animated = true,
}) {
callUIFunction(this.instance as Fiber, 'scrollToContentOffset', [xOffset, yOffset, animated]);
}
2.WaterfallView类中通过一个方法实现了item和banner的渲染,以下为其代码:
public render() {
const {
style = {},
renderBanner,
numberOfColumns = 2,
columnSpacing = 0,
interItemSpacing = 0,
numberOfItems = 0,
preloadItemNumber = 0,
renderItem,
renderPullHeader,
renderPullFooter,
getItemType,
getItemKey,
getItemStyle,
contentInset = { top: 0, left: 0, bottom: 0, right: 0 },
onItemLayout,
onHeaderPulling,
onHeaderReleased,
onFooterPulling,
onFooterReleased,
containPullHeader = false,
containPullFooter = false,
containBannerView = false,
...otherNativeProps
} = this.props as WaterfallViewProps;
const nativeProps = {
...otherNativeProps,
style,
numberOfColumns,
columnSpacing,
interItemSpacing,
preloadItemNumber,
contentInset,
containPullHeader,
containPullFooter,
containBannerView,
};
const itemList = [];
if (typeof renderBanner === 'function') {
const banner = renderBanner();
if (banner) {
itemList.push((
<View key="bannerView">
{React.cloneElement(banner)}
</View>
));
nativeProps.containBannerView = true;
}
}
if (typeof renderItem === 'function') {
const pullHeader = this.getPullHeader(renderPullHeader, onHeaderPulling, onHeaderReleased);
const pullFooter = this.getPullFooter(renderPullFooter, onFooterPulling, onFooterReleased);
for (let index = 0; index < numberOfItems; index += 1) {
const itemProps: WaterfallViewItemProps = {} as WaterfallViewItemProps;
const rowChildren = renderItem(index) || null;
this.handleRowProps(itemProps, index, { getItemKey, getItemStyle, getItemType, onItemLayout });
if (rowChildren) {
itemList.push((
// @ts-ignore
<WaterfallViewItem {...itemProps}>
{ rowChildren }
</WaterfallViewItem>
));
}
}
if (pullHeader) {
itemList.unshift(pullHeader);
nativeProps.containPullHeader = true;
}
if (pullFooter) {
itemList.push(pullFooter);
nativeProps.containPullFooter = true;
}
(nativeProps as WaterfallViewProps).style = {
...style,
};
} else {
warn('Waterfall attribute [renderItem] is not Function');
}
return (
// @ts-ignore
<ul
nativeName={'WaterfallView'}
ref={ref => this.instance = ref}
initialListReady={this.handleInitialListReady.bind(this)}
{...nativeProps}
>
{ itemList }
</ul>
);
}
瀑布流是现在流行的一种布局方式,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。hippy-react中也通过WaterfallView类来实现这种布局方式,并且提供了各种方法调用来方便代码编写,为网页布局的实现提供了很大的便利。