0

我的水平平面列表中有大约 10 个项目。我正在将 Ref 存储到每个项目,如下所示。

const Item = ({ title, image, index }) => {
  linkRefs[index] = useRef(null);

  return (
    <Animated.View ref={linkRefs[index]}>
      <Image
        resizeMode="cover"
        style={styles.tinyLogo}
        source={{
          uri: image,
        }}
      />
    </Animated.View>
  );
};

我想获得可见元素的 X 位置。所以我尝试了下面的代码,它工作正常。

 const Measure = () => {
       Object.keys(itemsY).forEach(function (key) {
        linkRefs[key].current.measure((x, y, width, height, pageX, pageY) => {
          if(typeof pageX != "undefined")
          {
            itemsY[key].setValue(pageX);
            console.log(key+"--"+pageX);
            console.log("width--"+width);
            console.log("---");
          }
        });
      });
    };

问题是测量仅适用于完全可见的项目。我什至想测量位置,即使它几乎不可见。我该怎么做?

我试过 itemVisiblePercentThreshold ,仍然测量只对完全可见的项目起作用。

 const viewabilityConfig = useRef({
    itemVisiblePercentThreshold:20
  }).current;     

 <Animated.FlatList
      horizontal
      pagingenabled
      snapToInterval={125}
      snapToAlignment="center"
      decelerationRate="fast"
      showsVerticalScrollIndicator={true}
      showsHorizontalScrollIndicator={false}
      data={DATA}
      renderItem={renderItem}
      keyExtractor={item => item.id}
      initialNumToRender={4}
      horizontal={true}
      viewabilityConfig={viewabilityConfig}
      />
4

1 回答 1

0

当我在玩 FlatList 时,我决定我想知道列表滚动的方向,所以我最终使用 onScroll 属性来获取该值:

import React , { useState, useRef,useCallback } from 'react';
import { SafeAreaView, Image , View, FlatList, StyleSheet, Text, StatusBar } from 'react-native';
import { Ionicons, MaterialCommunityIcons , FontAwesome5 } from "@expo/vector-icons";
import * as Animatable from 'react-native-animatable';
import FlatListWrapper from "../components/FlatListWrapper";



const FlatListAnimation = () => {
  const DATA = [
    {
      id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
      title: 'First  Item Item Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/scam_Lang_Protrait_Thumb.jpg'
    },
    {
      id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
      title: 'Second Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/Ramsingh-CharlieA_07062021_Lang_Protrait_Thumb.jpg'
    },
    {
      id: '58694a0f-3da1-471f-bd96-145571e29d72-3-3',
      title: 'Third Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/6028647473001.jpg'
  
    },
    {
      id: '58694a0sdsf-3da1-471f-bd96-145571e29d72-4-4',
      title: 'Fourth Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/6033313370001.jpg'
  
    },
    {
      id: '58694a0f-3ddsda1-471f-bd96-145571e29d72-5-5',
      title: 'Fifth Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/6033325319001_v2.jpg'
  
    },
    {
      id: 'bd7acbea-c1b1-46c2-aed5-3ad531abb28ba-6-6',
      title: 'Sixth  Item Item Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/scam_Lang_Protrait_Thumb.jpg'
    },
    {
      id: '3ac68afc-c605-48d3-a4f8-fbd912aa97f63-7-7',
      title: 'Seventh Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/Ramsingh-CharlieA_07062021_Lang_Protrait_Thumb.jpg'
    },
    {
      id: '58694a0f-3da1-471f-bd96-1455371e29d72-8-8',
      title: 'Eighth Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/6028647473001.jpg'
  
    },
    {
      id: '58694a0sdsf-3da1-471f-bd96-1445571e29d72-9-9',
      title: 'Ninth Item',
      image : 'https://res.cloudinary.com/Sony-liv/image/fetch/c_fill,e_brightness:10,f_auto,fl_lossy,h_494,q_auto:low,w_344/https://origin-staticv2.sonyliv.com/portrait_thumb/6033313370001.jpg'
  
    },
  ];
  const maxlimit = 20;
    // store the indices of the viewableItmes
  const [ viewableItemsIndices, setViewableItemsIndices ] = useState([]);
  const itemRefs = useRef(
    DATA.map( item=> {})
  );
  
  const isScrollingForward = useRef(true);
  // use last and current scroll position to determine scroll direction
  const lastScrollPosition = useRef(0);
  const handleScroll = ({nativeEvent})=>{
    let currentPosition = nativeEvent.contentOffset.x
    isScrollingForward.current = currentPosition > lastScrollPosition.current
    lastScrollPosition.current = currentPosition
  }
    // Item.js
  const Item = (props) => { 
    let {
      item:{ image , title, isViewable },
      index
    } = props
    return (
      //add animation to Animated.View
      <Animatable.View style={styles.itemContainer} ref={ref=>itemRefs[index]=ref} >
        <Image
          resizeMode="contain"
          style={styles.tinyLogo}
          source={{
            uri: image,
          }}
        />
      </Animatable.View>
    );
  }
  return (
    <SafeAreaView style={styles.container}>
      <FlatListWrapper
        horizontal={true}
        //{/*give each data item an isViewable prop*/}
        data={ DATA }
        renderItem={(item,i)=><Item {...item} />}
        keyExtractor={item => item.id}
        onViewableItemsChanged={({viewableItems, changed})=>{
          let duration = 2000;
          viewableItems.forEach(item=>{
            let itemRef = itemRefs[item.index];
            itemRef?.transitionTo({opacity:1},duration)
            isScrollingForward.current ? 
              itemRef?.bounceInRight() :
              itemRef?.bounceInLeft()
          })
          changed.forEach(item=>{
            let itemRef = itemRefs[item.index];
            if(!item.isViewable){
              itemRef?.transitionTo({opacity:0})
              isScrollingForward.current ? 
              itemRef?.bounceOutLeft() :
              itemRef?.bounceInRight()
            }
          })
        }}
        //{/*config that decides when an item is viewable*/} 
        viewabilityConfig={{itemVisiblePercentThreshold:100}}
        onScroll={handleScroll}
        disableScrollMomentum={true}
      />
     {/* Extra stuff that just tells you what items should be visible*/}
      <Text>Items that should be visible:</Text>
      {viewableItemsIndices.map(i=><Text key={'text-'+i}>  {DATA[i].title}</Text>)}
    </SafeAreaView>
  );
}
  
const styles = StyleSheet.create({
  container: {
    // flex: 1,
    marginTop: StatusBar.currentHeight || 0,
  },
  itemContainer: {
    opacity:0
  },
  title: {
    fontSize: 32,
  },
  tinyLogo: {
    borderRadius : 4,
    width: 150,
    height:150
  },
});

  export default FlatListAnimation; 
于 2021-06-18T20:19:38.647 回答