Reputation: 85
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
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
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-handler
with their PanGestureHandler this problem is prevented.
Upvotes: 3