iOS中SectionList开始滑动偶尔滑不动或卡顿

218 阅读1分钟

RN 0.66版本上,开发TabView里面有一个SectionList,这个SectionList开启了stickySectionHeaders,但是在iOS上开始滑动的时候,偶尔出现滑动不了或者要先卡顿一下,让人摸不着头脑

最后在RCTView调试hitTest:withEvent:时发现了,手势被SectionListCell响应了

- (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;
      }
    }
  }
  
  ...   
}

hitSubviewCell

可以在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>
);

可以看到SectionListrenderItem返回的视图并不是最终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>
      )}
    />