You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RN Animated.FlatList调用ScrollToIndex在Android出现闪烁问题

React Native FlatList无限轮播滑动跳转闪烁问题

我用FlatList实现了一个基于有限数据集的无限轮播组件,逻辑是滑动到末尾时通过ScrollToIndex方法跳转到开头,滑动到开头时跳转到末尾。但在Android平台,从最后一张横幅跳转至第一张时,ScrollToIndex会引发奇怪的闪烁现象,iOS也存在轻微不稳定的问题。

相关代码如下:

const Carousel = () => {

    const [activeBanner, setActiveBanner] = useState(0);
    const scrollX = useRef(new Animated.Value(0)).current;
    const listRef = useRef<RNFlatList>(null);

    const goToIndex = (index: number, animated: boolean) => {
        listRef.current?.scrollToIndex({
          index,
          animated,
        });
      };

    const handleScroll = (event: any) => {
        const { contentOffset } = event.nativeEvent;
        const currentIndex = Math.floor((contentOffset.x - 50) / FULL_BANNER_WIDTH);
        if (
          currentIndex >= banners.length &&
          contentOffset.x >= ACTIVE_BANNER_WIDTH * (banners.length + 1) - 20
        ) {
          goToIndex(1, false);
        } else if (currentIndex <= 0 && contentOffset.x <= 0) {
          goToIndex(banners.length, false);
        }
    }

    const itemLayout = (_data: any, index: number) => ({
        length: FULL_BANNER_WIDTH,
        offset: FULL_BANNER_WIDTH * index,
        index: index,
    });

    const onViewableItemsChangedHandler = (info: any) => {
        if (info.viewableItems.length > 0) {
          setActiveBanner(info.viewableItems[0].index - 1);
        } else {
          setActiveBanner(0);
        }
    };

    const viewConfigRef = React.useRef([
        {
          viewabilityConfig: {
            waitForInteraction: false,
            itemVisiblePercentThreshold: 100,
            minimumViewTime: 0,
          },
          onViewableItemsChanged: onViewableItemsChangedHandler,
        },
    ]);

    const flatlistMemo = React.useMemo(() => {
        return (
          <Animated.FlatList
            decelerationRate={0.9}
            disableIntervalMomentum={true}
            disableScrollViewPanResponder={true}
            snapToInterval={FULL_BANNER_WIDTH}
            horizontal={true}
            showsHorizontalScrollIndicator={false}
            ref={listRef}
            data={renderItem}
            renderItem={renderItems}
            keyExtractor={keyExtractor}
            onScroll={Animated.event(
              [{ nativeEvent: { contentOffset: { x: scrollX } } }],
              { useNativeDriver: true, listener: event => handleScroll(event) }
            )}
            scrollEventThrottle={16}
            onScrollToIndexFailed={onScrollFail}
            getItemLayout={itemLayout}
            onScrollBeginDrag={() => setIsDragging(true)}
            onScrollEndDrag={() => setIsDragging(false)}
            initialScrollIndex={1}
            contentContainerStyle={[
              styles.flatListContainer,
              {
                marginLeft: -HIDDEN_BANNER_PORTION,
              },
            ]}
            viewabilityConfigCallbackPairs={viewConfigRef.current}
          />
        );
      }, [renderItem]);
    
    return (
      <View>{flatlistMemo}</View>
    )
}

我已经尝试过以下解决方法,但都没解决问题:

  • 移除用于追踪当前横幅的setState
  • 添加/移除FlatList的memoization处理
  • 调整keyExtractor
  • 移除动画效果
  • 配置windowsize等参数
  • 改用ScrollView/ScrollTo方法

内容的提问来源于stack exchange,提问作者tammi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 15:15:36