【问题标题】:FlatList child items with absolute position does not work?具有绝对位置的 FlatList 子项不起作用?
【发布时间】:2020-07-25 08:45:12
【问题描述】:

我正在让 Tinder 在我的应用中滑动。我正在使用FlatList 来渲染像 Tinder 这样的卡片组。我已将position:absolute 分配给我的FlatList 中的renderItems 的根视图,这样每个FlatList 项目都在彼此后面,我可以滑动查看下一个项目。 FlatList 中的每张卡片都非常复杂,因此我必须使用 scrollview 来垂直滚动每张卡片,并且我禁用了平面列表滚动,因为我不希望平面列表滚动,因为项目放在一个后面其他。现在position:absolute 在 iOS 上可以正常工作,但在 android 上不行。我厌倦了将left, top,right and bottom 属性分配给父视图,但它仍然不起作用。我也试过elevation。我可以使用 map 而不是 flatlist,但是性能真的很差,因为数组中有很多项目,并且在使用 map 在 android 和 ios 上工作时保持position:absolute。我尝试使用 https://github.com/alexbrillant/react-native-deck-swiperhttps://github.com/archriss/react-native-snap-carousel,但由于我的 UI 的复杂性,它们并不能真正为我工作。

以下是 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>
  );

我在 flatlist 中的实际项目比上面的代码复杂得多。我尝试阅读有关此问题的不同 GitHub 问题以及堆栈溢出问题,但它们似乎对我不起作用。

我将这个 repo https://github.com/PlatypusIndustries/RNCardStack 称为 Tinder Swiping 的示例

如何在Android中将FlatList的每一项设置为绝对位置?

编辑:

通过将以下属性添加到我的 FlatList contentContainerStyle={{flexGrow:1,borderWidth:1}},我能够在 Android 中显示项目,但我的 FlatList 中每个项目的平移响应器在 Android 上不起作用,因为每个项目的位置都是绝对的。我也尝试添加elevation,zIndex,top,left,right,bottom 属性。我尝试将Animated.View 包装在View 中并将位置应用于该视图,但仍然无法在Android 中工作。我尝试将其包装在 TouchableOpacityTouchableWithoutFeedback 中,但它不起作用。我尝试了来自react-nativereact-native-gesture-handlerTouchableOpacityTouchableWithoutFeedback。当我删除 position:absolute 时,我的 Pan 响应程序代码有效,所以那里没有问题

这是我的 pan 响应器代码

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();
      }
    },
  });

【问题讨论】:

  • 能否展示PanResponder相关代码和rotateAndTranslate样式?
  • @VadimGoroshevsky 我已经添加了代码,请检查,我认为我的 pan 响应器代码没有问题,因为它在 iOS 上工作,即使位置是绝对的。当我删除位置绝对代码时,它甚至可以在 android 上运行
  • 我已经在我的项目中创建了 tinder 选项卡,但由于保密协议,我无法共享代码。我将为火种标签制作单独的包装
  • @MuhammadNuman 您的平面列表中的每个项目是否也可以垂直滚动。
  • 是的,它也可以垂直工作。您可以在 LinkedIn 上连接到我,并可以私聊。 numan.dev

标签: android react-native react-native-flatlist


【解决方案1】:

前段时间我在 FlatList 上的 Pan Gesture 遇到了一些问题,我的解决方案是使用 react-native-gesture-handler 的 FlatList 和 PanGestureHandler。您遇到的问题是 FlatList 覆盖了卡片中的手势,当您使用 react-native-gesture-handler 的 FlatList 和他们的 PanGestureHandler 时,可以防止此问题。

【讨论】:

  • 我将不得不使用 PanGestureHandler 再次编写滑动火种代码。本身就是一项艰巨的任务
【解决方案2】:

具有绝对位置的FlatList 项目在Android 上不可见。这里链接打开问题https://github.com/facebook/react-native/issues/29867

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-28
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 2011-04-19
    • 2017-05-13
    相关资源
    最近更新 更多