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

为什么选中FlatList内的元素时,列表会自动滚动到顶部?

问题根因

你遇到的FlatList选中子项后自动滚动到顶部的问题,核心是触发了FlatList的全量重绘,无法保留原滚动位置,具体诱因在你的代码里有两处:

  1. RenderBrand 和 BrandSeparator 组件定义在 FilterOptionBrand 内部,每次选中子项修改tempFilterOptions触发组件重渲染时,这两个组件都会被重新创建,FlatList会判定renderItem和ItemSeparatorComponent属性发生变更,因此重新渲染所有列表项,重置滚动位置。
  2. 未给FlatList配置getItemLayout属性,动态数据更新时FlatList无法预计算每个item的位置,布局重计算后会默认回到初始滚动位置。

修复方案

  • 把RenderBrand、BrandSeparator组件移到FilterOptionBrand外部,需要用到的setBrandSelected等方法通过props传递,避免每次重渲染生成新组件
  • 优化状态更新逻辑,用函数式更新代替深拷贝,避免状态依赖导致的不必要重渲染,同时性能更好。

参考调整后的代码:

// 移到FilterOptionBrand组件外部定义
const RenderBrand = ({ item, index, onPress }) => {
  return (
    <TouchableOpacity onPress={() => onPress(index)}>
      {item.selected && (
        <View style={[styles.brandImage, styles.selectedBrandImage]}>
          <Icon iconName={iconNames.Tick} />
        </View>
      )}
      <FastImage source={{ uri: item.logo }} style={styles.brandImage} resizeMode={FastImage.resizeMode.contain} />
      <Text style={styles.brandName}>{item.name}</Text>
    </TouchableOpacity>
  );
};

const BrandSeparator = () => <View style={styles.brandSeparator} />;

const FilterOptionBrand = () => {
  const setBrandSelected = index => {
    // 改用函数式更新,避免依赖外部状态
    setTempFilterOptions(prev => {
      const newOptions = [...prev];
      const newEnums = [...newOptions[0].enums];
      newEnums[index] = {
        ...newEnums[index],
        selected: !newEnums[index].selected
      };
      newOptions[0] = {
        ...newOptions[0],
        enums: newEnums
      };
      return newOptions;
    });
  };

  return (
    <View style={styles.filterBrandMainContainer}>
      <View style={styles.searchBrandContainer}>
        <View style={styles.magnifyingGlassWrapper}>
          <Icon iconName={iconNames.MagnifyingGlass} />
        </View>
        <TextInput style={styles.searchBrandInput} placeholder={searchBrandText} />
      </View>
      <FlatList
        horizontal={true}
        showsHorizontalScrollIndicator={false}
        keyExtractor={(item, index) => String(item.id)}
        style={styles.collapsibleContainer}
        data={tempFilterOptions[0].enums}
        renderItem={({item, index}) => <RenderBrand item={item} index={index} onPress={setBrandSelected} />}
        ItemSeparatorComponent={BrandSeparator}
        // 新增getItemLayout配置,替换成你实际的item宽度和分隔符宽度
        getItemLayout={(data, index) => {
          const itemWidth = 80; // 替换为你的品牌项实际总宽度
          const separatorWidth = 12; // 替换为你的分隔符实际宽度
          return {
            length: itemWidth + separatorWidth,
            offset: (itemWidth + separatorWidth) * index,
            index
          }
        }}
      />
    </View>
  );
};

问题复现效果:
问题复现效果

内容的提问来源于stack exchange,提问作者Erkan GÖRGÜLÜ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 13:45:03