0

I'm trying to accomplish the vertical carousel as shown in the below gif. I'm struck by the second screen, where when the user scrolls the data from bottom to top or vice versa both the content and image change, how to achieve this? looking forward to your help?enter image description here

1 Answers1

-1

I have included a snack example which is mostly similar to what you want. You can use reanimated, Flatlist achieve the animation:

Snack Link

Code:

import * as React from 'react';
import { Text, View, StyleSheet, FlatList, Dimensions } from 'react-native';
import Constants from 'expo-constants';
import Animated, {
  useSharedValue,
  useAnimatedScrollHandler,
  useAnimatedStyle,
  interpolate,
  Extrapolate,
} from 'react-native-reanimated';
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);

const { width, height } = Dimensions.get('window');

const bottomHeight = height - 150 - 30 - Constants.statusBarHeight;

const data = [
  {
    title: 'data1',
    image:
      'https://assets.website-files.com/5f204aba8e0f187e7fb85a87/5f210a533185e7434d9efcab_hero%20img.jpg',
  },
  {
    title: 'data2',
    image:
      'https://www.whoa.in/201604-Whoa/10-alone-broken-image-mobile-wallpaper-hd-image.jpg',
  },
  {
    title: 'data3',
    image:
      'https://images.pexels.com/photos/674010/pexels-photo-674010.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
  },
  {
    title: 'data4',
    image:
      'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTntlma5HASL0HAM-KiC01A-JX4MxKousAA6A&usqp=CAU',
  },
];


const ImageContent = ({ image, scrollValue, index }) => {

  const animatedStyle = useAnimatedStyle(() => {
    const inputRange = [index * bottomHeight, (index + 1) * bottomHeight];
    const translateY = interpolate(
      scrollValue.value,
      inputRange,
      [0, -150],
      Extrapolate.CLAMP
    );
    return {
      transform: [{ translateY }],
    };
  });
  return (
    <Animated.Image
      source={{ uri: image }}
      style={[styles.image, { zIndex: data.length - index }, animatedStyle]}
      resizeMode="cover"
    />
  );
};

const TopPart = React.memo(({ scrollValue }) => {
  return (
    <View style={styles.topPartContainer}>
      {data.map(({ image }, index) => (
        <ImageContent {...{ scrollValue, image, index }} />
      ))}
    </View>
  );
});

const Item = ({ item, index }) => {
  return (
    <View
      style={[
        styles.item,
      ]}>
      <Text style={{ color: 'red' }}>{item.title}</Text>
    </View>
  );
};


const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  },
  topPartContainer: {
    width: 150,
    height: 150,
    borderRadius: 75,
    alignSelf: 'center',
    overflow: 'hidden',
  },
  image: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: '#fff',
    borderRadius: 75,
  },
  item: {
    width,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    height: bottomHeight,
  },
});

function App() {
  const scrollValue = useSharedValue(0);

  const handler = useAnimatedScrollHandler((event) => {
    scrollValue.value = event.contentOffset.y;
  });
  return (
    <View style={styles.container}>
      <TopPart {...{ scrollValue }} />
      <View style={{ flex: 1, paddingTop: 30, height: bottomHeight }}>
        <AnimatedFlatList
          contentContainerStyle={{ height: data.length * bottomHeight }}
          showsVerticalScrollIndicator={false}
          onScroll={handler}
          scrollEventThrottle={16}
          data={data}
          pagingEnabled
          keyExtractor={(item) => item.title}
          renderItem={({ item, index }) => <Item {...{ item, index }} />}
        />
      </View>
    </View>
  );
}
halfer
  • 19,824
  • 17
  • 99
  • 186
Ashwith Saldanha
  • 1,700
  • 1
  • 5
  • 15
  • Simply Awesome mate. Thanks for this. But, I'm stuck when it comes to using this with the tab navigator. Not sure how to sync this with the tab navigator. – Ajaykumar Rajasekaran Jan 06 '22 at 09:32
  • Ashwith: please consider using the word "you" rather than the txtspk "u" when writing here. Stack Overflow is more akin to documentation than a chatroom. – halfer Feb 06 '22 at 10:38