在React Native中拖动FlatList时防止按下激活



我正在使用一个转盘库(使用FlatList(在React Native中拖动东西。

我有这个旋转木马:

import * as React from "react";
import Carousel from "react-native-reanimated-carousel";
import Card from "components/cards/Card";
function CardCarousel(props) {
  return (
    <Carousel
      scrollAnimationDuration={200}
      width={300}
      windowSize={9}
      moveSize={5}
      style={{
        width: 2000,
        height: 300,
      }}
      data={props.articleGroup.data}
      renderItem={(article, index) => (
        <Card
          article={article.item}
          key={index + "-main-" + props.articleGroup.category}
        />
      )}
    />
  );
}
export default CardCarousel;

然后我的卡片看起来是这样的:

const Card = (props) => {
  const [bookmark, setBookmark] = useState(props.article.bookmark);
  const cdnURL = wrapImgCDN(props.article.image, 400);
  const routeChange = async (event) => {
    ... code to change route
  };
  const _bookmarkToggle = () => {
    bookmarkToggle(props.article);
    setBookmark(!bookmark);
  };
  return (
    <Pressable
      onPress={routeChange}
    >
      <WhiteCard
        {...props}
        _bookmarkToggle={_bookmarkToggle}
        cdnURL={cdnURL}
        bookmark={bookmark}
      />
    </Pressable>
  );
};

当我拖动平面列表时,如果我抓住其中一个<Card />项目,它会点击并更改到给定卡片的路线,但我不想允许用户点击卡片,除非滚动停止/用户根本没有拖动。

我该怎么做?

由于您正在将carousel的渲染项目包装到Pressable中,并在其onPress功能中激发routeChange,因此只要您按下转盘中的其中一个项目,它就会更改路线。

我们可以使用react原生重新激活的转盘组件的onSnapToItem回调函数。此函数作为道具传递给组件,一旦FlatList中的项目"捕捉",就会立即调用。它接收将被捕捉的项目的索引。我们可以将其与当前项进行比较,每当它发生变化时,我们都会向Card组件传递一个布尔属性。

可以像往常一样通过getCurrentIndex功能使用ref来访问current index

请注意,这需要一个附加状态。但是,只有当项目实际发生了更改,即新项目snapped into position时,我们才会更改状态。

布尔状态对于当前捕捉的项将为true,对于其他项将为false。我们对Card组件中useEffect中的fireRouteChange道具变化作出反应。

function CardCarousel(props) {
  const ref = React.useRef(null);
  const [currentIndex, setCurrentIndex] = React.useState(0);
  return (
    <Carousel
      ref={ref}
      onSnapToItem={(index) => index !== ref.current.getCurrentIndex() && setCurrentIndex(index)}
      scrollAnimationDuration={200}
      width={300}
      windowSize={9}
      moveSize={5}
      style={{
        width: 2000,
        height: 300,
      }}
      data={props.articleGroup.data}
      renderItem={(article, index) => (
        <Card
          article={article.item}
          fireRouteChange={currentIndex === index}
          key={index + "-main-" + props.articleGroup.category}
        />
      )}
    />
  );
}
const Card = (props) => {
  const [bookmark, setBookmark] = useState(props.article.bookmark);
  const cdnURL = wrapImgCDN(props.article.image, 400);
  React.useEffect(() => {
    if(props.fireRouteChange) {
       ... code to change route
    }
  }, [props.fireRouteChange])
  const _bookmarkToggle = () => {
    bookmarkToggle(props.article);
    setBookmark(!bookmark);
  };
  return (
      <WhiteCard
        {...props}
        _bookmarkToggle={_bookmarkToggle}
        cdnURL={cdnURL}
        bookmark={bookmark}
      />
  );
};

假设:routeChange函数可以位于CardCarousel

如果我们假设routeChange函数可以位于CardCarousel中,则可以使这一点更简单。我无法访问此功能的实现细节,因此我通过做出此假设将其包含在此处。

function CardCarousel(props) {
  const ref = React.useRef(null);
 function routeChange(index) {
    ... code to change route of the current snapped index
 };
  return (
    <Carousel
      ref={ref}
      onSnapToItem={(index) => index !== ref.current.getCurrentIndex() && fireRouteChange(index)}
      scrollAnimationDuration={200}
      width={300}
      windowSize={9}
      moveSize={5}
      style={{
        width: 2000,
        height: 300,
      }}
      data={props.articleGroup.data}
      renderItem={(article, index) => (
        <Card
          article={article.item}
          fireRouteChange={currentIndex === index}
          key={index + "-main-" + props.articleGroup.category}
        />
      )}
    />
  );
}
const Card = (props) => {
  const [bookmark, setBookmark] = useState(props.article.bookmark);
  const cdnURL = wrapImgCDN(props.article.image, 400);
  const _bookmarkToggle = () => {
    bookmarkToggle(props.article);
    setBookmark(!bookmark);
  };
  return (
      <WhiteCard
        {...props}
        _bookmarkToggle={_bookmarkToggle}
        cdnURL={cdnURL}
        bookmark={bookmark}
      />
  );
};

在用户滚动时禁用onPress功能

如果您想在用户滚动时禁用onPress功能,而只在转盘捕捉到位时才允许使用,则可以使用状态以及onScrollBeginonScollEnd功能。

function CardCarousel(props) {
  const [allowRouteChange, setAllowRouteChange] = useState(true) 
  return (
    <Carousel
      scrollAnimationDuration={200}
      width={300}
      windowSize={9}
      moveSize={5}
      onScrollBegin={() => setAllowRouteChange(false)}
      onScrollEnd={() => setAllowRouteChange(true)}
      style={{
        width: 2000,
        height: 300,
      }}
      data={props.articleGroup.data}
      renderItem={(article, index) => (
        <Card
          allowRouteChange={allowRouteChange}
          article={article.item}
          key={index + "-main-" + props.articleGroup.category}
        />
      )}
    />
  );
}
const Card = (props) => {
  const [bookmark, setBookmark] = useState(props.article.bookmark);
  const cdnURL = wrapImgCDN(props.article.image, 400);
  const routeChange = async (event) => {
    if (props.allowRouteChange) {
           ... code to change route
    }
  };
  const _bookmarkToggle = () => {
    bookmarkToggle(props.article);
    setBookmark(!bookmark);
  };
  return (
    <Pressable
      onPress={routeChange}
    >
      <WhiteCard
        {...props}
        _bookmarkToggle={_bookmarkToggle}
        cdnURL={cdnURL}
        bookmark={bookmark}
      />
    </Pressable>
  );
};

最新更新