RN 0.66版本上,开发TabView
里面有一个SectionList
,这个SectionList
开启了stickySectionHeaders,但是在iOS上开始滑动的时候,偶尔
出现滑动不了或者要先卡顿一下,让人摸不着头脑
最后在RCTView
调试hitTest:withEvent:
时发现了,手势被SectionList
的Cell
响应了
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
BOOL canReceiveTouchEvents = ([self isUserInteractionEnabled] && ![self isHidden]);
if (!canReceiveTouchEvents) {
return nil;
}
UIView *hitSubview = nil;
BOOL isPointInside = [self pointInside:point withEvent:event];
BOOL needsHitSubview = !(_pointerEvents == RCTPointerEventsNone || _pointerEvents == RCTPointerEventsBoxOnly);
if (needsHitSubview && (![self clipsToBounds] || isPointInside)) {
NSArray<UIView *> *sortedSubviews = [self reactZIndexSortedSubviews];
for (UIView *subview in [sortedSubviews reverseObjectEnumerator]) {
CGPoint convertedPoint = [subview convertPoint:point fromView:self];
hitSubview = [subview hitTest:convertedPoint withEvent:event];
if (hitSubview != nil) {
break;
}
}
}
...
}
hitSubview
是Cell
可以在VirtualizedList中发现它render中的的如下方法
# 通过props的renderItem生产element
const {renderItem, getItemLayout, ListItemComponent} = parentProps;
const element = this._renderElement(
renderItem,
ListItemComponent,
item,
index,
);
# 再用一层Cell包裹生成的element
const cellStyle = inversionStyle
? horizontal
? [styles.rowReverse, inversionStyle]
: [styles.columnReverse, inversionStyle]
: horizontal
? [styles.row, inversionStyle]
: inversionStyle;
const result = !CellRendererComponent ? (
<View style={cellStyle} onLayout={onLayout}>
{element}
{itemSeparator}
</View>
) : (
<CellRendererComponent
{...this.props}
style={cellStyle}
onLayout={onLayout}>
{element}
{itemSeparator}
</CellRendererComponent>
);
可以看到SectionList
的renderItem
返回的视图并不是最终Cell
,如果不设置CellRendererComponent
则默认再用一层View包裹,所以要禁止每行Cell的手势,直接在renderItem设置pointerEvents="none"
中无效
所以最终为SectionList
设置一个CellRendererComponent
组件并禁止了它的手势响应,解决了开头的问题
测试代码块
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item, index }) => <Item item={item} index={index} />}
initialNumToRender={24}
maxToRenderPerBatch={48}
windowSize={21}
stickySectionHeadersEnabled
CellRendererComponent={props => <View {...props} pointerEvents="none" />}
renderSectionHeader={({ section: { title } }) => (
<View style={styles.header}>
<Text style={styles.headerText}>{title}</Text>
</View>
)}
/>