当我在玩 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;