skip to Main Content

I want to make a flatlist with three items and the selected/current Index item should be bigger as the two items next to.

enter image description here

Current Code:

  const translateX = useSharedValue(0);

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

  const animatedStyle = useAnimatedStyle(() => {
    const scale = interpolate(translateX.value, [width / 3, 0, width / 3], [0.2, 1, 0.2], Extrapolate.CLAMP);
    return {
      transform: [{
        scale
      }]
    }
  }, []);

  const renderI = ({ item }) => (
    <Animated.View style={[animatedStyle]}>
      <ProductCardAuto
        {...item}
        onPressProduct={() => handleNavigateToProduct(item)}
        onPressReviews={handleOpenModalReviews}
      />
    </Animated.View>
  )

    <Animated.FlatList
        data={mockProducts}
        renderItem={renderI}
        keyExtractor={(item) => item.id}
        snapToAlignment="start"
        decelerationRate={"normal"}
        onScroll={scrollHandler}
        horizontal
        snapToInterval={120}
    />

I am very thankful for your help. Idk what I am doing wrong. Maybe you can tell me what is wrong with it. it does not work its scale all items to 0.2 if I scroll

2

Answers


  1. kindof tried to make it acc to what you needed.

    You can check this expo : https://snack.expo.dev/d_myr1HdyN

    import React,{useState,useEffect,useRef,useCallback} from 'react';
    import { Text, View, StyleSheet ,Animated,FlatList,Dimensions,Easing } from 'react-native';
    import Constants from 'expo-constants';
    
    // You can import from local files
    import AssetExample from './components/AssetExample';
    
    // or any pure javascript modules available in npm
    import { Card } from 'react-native-paper';
    
    const data = ["hey there","indian","mango","whatsup","arsenal","jojoba"]
    
    const screenWidth = Dimensions.get("window").width;
    
    
    const EachItem = (props) => {
      const {text = "",index=0,currentView={}} = props || {}
    
      const {visible = false, index:visibleIndex = 0} = currentView;
    
      console.log(visible,visibleIndex,"wuhyyyyy")
    
      const animRef = useRef(new Animated.Value(0)).current
    
      const startAnimation = useCallback(() => {
        Animated.timing(animRef,{
          toValue:1,
          duration:1000,
          useNativeDriver:true,
          easing:Easing.ease,
        }).start()
      },[animRef])
    
        const stopAnim = useCallback(() => {
        Animated.timing(animRef,{
          toValue:0,
          duration:1000,
          useNativeDriver:true,
          easing:Easing.ease,
        }).start()
      },[animRef])
    
      useEffect(() => {
        if(visible === true && visibleIndex===index ){
    startAnimation()
        }
    
        if(visible === false  ){
      setTimeout(() =>stopAnim(),1000)
        }
    
      },[startAnimation,visible,visibleIndex,index,stopAnim])
    
      const scaleInter = animRef.interpolate({inputRange:[0,1],outputRange:[1,1.5]})
    
      return(
        <Animated.View style={{marginHorizontal:20 ,height:100,
        backgroundColor:'rgba(102,116,255,0.6)',
        width:screenWidth/3,
        alignItems:'center',
        justifyContent:'center',
        transform:[{
          scale:scaleInter
        }]
        }}  >
       
        <Text>{text}</Text>
      
        </Animated.View>
      )
    }
    
    export default function App() {
    
      const [currentView,setCurrentView] = useState({visible:false,index:null})
      
    
      const onViewRef = React.useRef((viewableItems) => {
        console.log(viewableItems?.viewableItems,"viewableItems")
    
      if(viewableItems?.viewableItems.length === 2){
        setCurrentView({visible:false,index:null})
      }
    
      if(viewableItems?.viewableItems.length === 1){
        const currentItemIndex = viewableItems?.viewableItems[0]?.index
         setCurrentView({visible:true,index:currentItemIndex})
      }
    
      });
    
      const viewConfigRef = React.useRef({ viewAreaCoveragePercentThreshold: 30 });
    
      const eachItem = ({item,index}) => {
        return <EachItem text={item} currentView={currentView} index={index} />
      }
    
      return (
        <View style={styles.container}>
         <Animated.FlatList 
         data={data}
         style={{flex:1}}
         contentContainerStyle={{paddingTop:100}}
         horizontal={true}
         onViewableItemsChanged={onViewRef.current}
            viewabilityConfig={viewConfigRef.current}
            renderItem={eachItem}
         />
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        // justifyContent: 'center',
        paddingTop: Constants.statusBarHeight,
        backgroundColor: '#ecf0f1',
        padding: 8,
        // alignItems:'center'
      },
      paragraph: {
        margin: 24,
        fontSize: 18,
        fontWeight: 'bold',
        textAlign: 'center',
      },
    });

    Hope it helps. feel free for doubtsenter image description here

    Login or Signup to reply.
  2. Even if the question has been already answered, I would suggest another approach.

    What worked for me is react-native-reanimated-carousel, which not only that is very easy to use and very customizable, but is also using react-native-reanimated and that means native performance and precise animations because it runs the animations on the UI thread rather than the JS thread.

    EDIT: I noticed that you’re actually looking for a reanimated answer, which is great!

    Based on the library I showed you, I believe you’re looking for a parallax horizontal.

    Here’s a link to the example: https://github.com/dohooo/react-native-reanimated-carousel/blob/main/exampleExpo/src/pages/parallax/index.tsx

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search