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

React Native Reanimated实现FlatList选中项放大效果故障排查

解决React Native横向FlatList选中项放大的问题

问题根源分析

你的代码存在三个核心问题,导致所有列表项同步缩放:

  • 所有列表项共享同一个动画样式,无法单独控制每个项的缩放逻辑
  • 插值函数的输入范围设置错误([width / 3, 0, width / 3]不是递增序列),导致插值逻辑完全失效
  • 未基于每个列表项的位置计算相对偏移,无法区分当前选中项与其他项的差异

修复后的完整代码

import { useWindowDimensions } from 'react-native';
import Animated, { useSharedValue, useAnimatedScrollHandler, useAnimatedStyle, interpolate, Extrapolate } from 'react-native-reanimated';

// 你的其他组件/函数导入...

const YourComponent = () => {
  const { width: screenWidth } = useWindowDimensions();
  const translateX = useSharedValue(0);
  const ITEM_WIDTH = 120; // 与snapToInterval保持一致

  const scrollHandler = useAnimatedScrollHandler({
    onScroll: (e) => {
      translateX.value = e.contentOffset.x;
    }
  });

  // 为每个列表项单独生成动画样式
  const getAnimatedStyle = (index) => {
    return useAnimatedStyle(() => {
      // 计算当前项中心与滚动区域中心的距离
      const itemCenter = index * ITEM_WIDTH + ITEM_WIDTH / 2;
      const scrollCenter = translateX.value + screenWidth / 2;
      const distance = Math.abs(itemCenter - scrollCenter);

      // 根据距离插值:中心项缩放1,远离中心的项逐步缩到0.2
      const scale = interpolate(
        distance,
        [0, ITEM_WIDTH],
        [1, 0.2],
        Extrapolate.CLAMP
      );

      return {
        transform: [{ scale }]
      };
    }, [index]);
  };

  const renderItem = ({ item, index }) => {
    const animatedStyle = getAnimatedStyle(index);
    return (
      <Animated.View style={[{ width: ITEM_WIDTH }, animatedStyle]}>
        <ProductCardAuto
          {...item}
          onPressProduct={() => handleNavigateToProduct(item)}
          onPressReviews={handleOpenModalReviews}
        />
      </Animated.View>
    );
  };

  return (
    <Animated.FlatList
      data={mockProducts}
      renderItem={renderItem}
      keyExtractor={(item) => item.id}
      snapToAlignment="center" // 改为居中对齐,确保选中项在屏幕中间
      decelerationRate="fast"
      onScroll={scrollHandler}
      horizontal
      snapToInterval={ITEM_WIDTH}
      contentContainerStyle={{ paddingHorizontal: (screenWidth - ITEM_WIDTH) / 2 }} // 左右留白,让首尾项也能居中
    />
  );
};

export default YourComponent;

关键修改说明

  • 独立动画样式:通过getAnimatedStyle为每个列表项生成专属动画,避免所有项同步缩放
  • 位置驱动的插值逻辑:基于项的中心与滚动区域中心的距离计算缩放值,实现中心项放大、边缘项缩小的效果
  • 修正FlatList配置:改为居中对齐并添加左右留白,确保交互时项能准确停在屏幕中心,提升体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:50:27