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

如何实现FlatList刷新时不自动滚动到顶部 保持当前滚动位置

FlatList触发刷新时自动滚动到顶部的解决方法

问题复现代码

存在异常的组件原有实现如下:

<FlatList
  style={styles.flatList}
  contentContainerStyle={styles.flatListContent}
  keyExtractor={keyExtractor}
  renderItem={renderItem}
  data={data}
  ref={flatListRef}
  refreshControl={
    <RefreshControl
      style={{ transform: [{ scale: 0.8 }] }}
      refreshing={isRefreshing}
      onRefresh={async () => {
        setRefreshing(true);
        //fetch
        setRefreshing(false);
      }}
    />
  }
/>

核心诱因

  • 给RefreshControl设置transform缩放样式,会干扰原生端滚动位置计算,触发刷新时自动重置内容偏移
  • 刷新状态切换时列表重渲染,未主动保持滚动位置
  • key配置不稳定时,重渲染会导致元素位置计算错乱

修复方案

按优先级操作即可解决问题:

  • 移除RefreshControl上的transform自定义缩放样式
    调整刷新指示器样式优先用原生提供的属性:Android端用size属性控制大小,iOS端用tintColor、progressViewOffset调整样式,不要通过CSS transform修改组件缩放。
  • 主动记录并恢复滚动位置
    新增ref存储滚动偏移量,在刷新流程结束后将列表滚回原位置,参考实现:
import { useRef } from 'react';
// 组件内新增滚动位置存储ref
const scrollOffsetRef = useRef(0);

<FlatList
  // 保留原有所有属性
  onScroll={(e) => {
    scrollOffsetRef.current = e.nativeEvent.contentOffset.y;
  }}
  scrollEventThrottle={16}
  refreshControl={
    <RefreshControl
      refreshing={isRefreshing}
      onRefresh={async () => {
        const savedOffset = scrollOffsetRef.current;
        setRefreshing(true);
        // 执行原有数据拉取逻辑
        await fetchYourData();
        setRefreshing(false);
        // 等待布局更新完成后恢复滚动位置
        requestAnimationFrame(() => {
          flatListRef.current?.scrollToOffset({
            offset: savedOffset,
            animated: false
          });
        });
      }}
    />
  }
/>
  • 配置稳定key与原生位置保持属性
    • 确保keyExtractor返回每一项的唯一、固定业务ID,禁止使用数组索引作为key
    • React Native 0.72及以上版本可直接给FlatList添加maintainVisibleContentPosition={{minIndexForVisible: 0, autoscrollToTopThreshold: 0}}属性,从原生层面自动维持可见内容位置,不需要手动写滚动恢复逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:09:26