BraveEvidence
BraveEvidence

Reputation: 85

FlatList child items with absolute position does not work?

I am making Tinder swipe in my app. I am using FlatList to render deck of cards like Tinder. I have assigned position:absolute to the root view of renderItems in my FlatList so that each FlatList items are behind each other and I can swipe to see the next item. Each of the card in my FlatList is very complex so I have to use scrollview for vertical scrolling of each card and I have disabled the flat list scrolling as I don't want the flatlist to scroll as items are placed behind one another. Now position:absolute works fine on iOS but does not work on android. I tired assigning left, top,right and bottom properties to the parent view but still it won't work. I tried elevation as well. I can use map instead of flatlist but then the performance is really bad as there are lot of item in the array and keeping position:absolute when using map works on android and ios. I tried using https://github.com/alexbrillant/react-native-deck-swiper and https://github.com/archriss/react-native-snap-carousel but they don't really work for me due to the complexity of my UI.

Following is a simple example of each item in the Flatlist

return (
    <Animated.View
      {...panResponder.panHandlers}
      style={[
        rotateAndTranslate,
        {
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          position: "absolute",
          elevation: 1000,
        },
      ]}
    >
        <Text>{index}</Text>
    </Animated.View>
  );

My actual items in flatlist are much more complex than the above code. I tried reading different GitHub issues on this as well as stack overflow questions but they don't seem to work for me.

I am referring this repo https://github.com/PlatypusIndustries/RNCardStack as a sample eg for Tinder Swiping

How to make position as absolute for each item of FlatList in Android?

Edit:

I was able to display items in Android by adding the following property to my FlatList contentContainerStyle={{flexGrow:1,borderWidth:1}} but the pan responder of each item in my FlatList won't work on Android as the position of each item is absolute. I tried adding elevation,zIndex,top,left,right,bottom properties as well. I tried wrapping Animated.View inside a View and applying position to that view but still won't work in Android. I tried wrapping it inside TouchableOpacity and TouchableWithoutFeedback but it won't work. I tried TouchableOpacity and TouchableWithoutFeedback both from react-native as well as react-native-gesture-handler. My Pan responder code works when I remove position:absolute so no issue there

Here is my pan responder code

let position = useRef(new Animated.ValueXY()).current;
  // const [currentIndex, setCurrentIndex] = useState(0);

  let rotate = position.x.interpolate({
    inputRange: [-width / 2, 0, width / 2],
    outputRange: ["-30deg", "0deg", "10deg"],
    extrapolate: "clamp",
  });

  let rotateAndTranslate = {
    transform: [
      {
        rotate: rotate,
      },
      ...position.getTranslateTransform(),
    ],
  };

  let likeOpacity = position.x.interpolate({
    inputRange: [-width / 2, 0, width / 2],
    outputRange: [0, 0, 1],
    extrapolate: "clamp",
  });
  let dislikeOpacity = position.x.interpolate({
    inputRange: [-width / 2, 0, width / 2],
    outputRange: [1, 0, 0],
    extrapolate: "clamp",
  });

  const panResponder = PanResponder.create({
    // onShouldBlockNativeResponder: () => true,
    onMoveShouldSetPanResponderCapture: (event, gestureState) => {
      // console.log(gestureState.dx);
      if (gestureState.dx === 0 || gestureState.dy === 0) {
        return false;
      }

      return true;
    },
    onPanResponderTerminationRequest: () => false,
    onStartShouldSetPanResponderCapture: () => false,
    onStartShouldSetPanResponder: (evt, gestureState) => false,
    onPanResponderMove: (evt, gestureState) => {
      // console.log(gestureState.dx);
      // console.log("here " + width * 0.1);
      if (gestureState.dx < width * 0.1 && gestureState.dx > -width * 0.1) {
        return true;
      }

      position.setValue({ x: gestureState.dx, y: gestureState.dy });
    },
    onPanResponderRelease: (evt, gestureState) => {
      // console.log(gestureState.dx);
      if (gestureState.dx > 120) {
        // console.log(gestureState.dy);

        Animated.spring(position, {
          toValue: {
            x: width + 100,
            y: gestureState.dy,
          },
          useNativeDriver: true,
        }).start(() => {
          handleRemove(index);
        });
      } else if (gestureState.dx < -120) {
        // console.log(gestureState.dy);

        Animated.spring(position, {
          toValue: { x: -width - 180, y: gestureState.dy },
          useNativeDriver: true,
        }).start(() => {
          handleRemove(index);
        });
      } else {
        Animated.spring(position, {
          toValue: { x: 0, y: 0 },
          friction: 10,
          useNativeDriver: true,
        }).start();
      }
    },
  });

Upvotes: 1

Views: 2010

Answers (2)

Dat Nguyen
Dat Nguyen

Reputation: 1

FlatList items with absolute position are not visible on Android. here link open issue https://github.com/facebook/react-native/issues/29867

Upvotes: 0

Tiago Boer Casagrande
Tiago Boer Casagrande

Reputation: 131

I had some problems with Pan Gesture on FlatList some time ago, my solution was use the FlatList and the PanGestureHandler from react-native-gesture-handler. The problem that you are having is that the FlatList is overriding the gestures from the cards, when you use the FlatList from react-native-gesture-handlerwith their PanGestureHandler this problem is prevented.

Upvotes: 3

Related Questions