I'm trying to implement a custom refresher animation to my app and im almost there. It just seems like i can't fix this glitch but I know it's possible because the native RefreshControl is so smooth. Here is a video of what I currently have: https://youtu.be/4lMn2sVXBAM
In this video, you can see how it scrolls past where it's supposed to stop once you release the flatlist and then it jumps back to where it's meant to stop. I just want it to be smooth and not go past the necessary stop so it doesn't look glitchy. Here is my code:
@inject('store')
@observer
class VolesFeedScreen extends Component<HomeFeed> {
@observable voleData:any = [];
@observable newVoleData:any = [1]; // needs to have length in the beginning
@observable error:any = null;
@observable lastVoleTimestamp: any = null;
@observable loadingMoreRefreshing: boolean = false;
@observable refreshing:boolean = true;
@observable lottieViewRef: any = React.createRef();
@observable flatListRef: any = React.createRef();
@observable offsetY: number = 0;
@observable animationSpeed: any = 0;
@observable extraPaddingTop: any = 0;
async componentDidMount(){
this.animationSpeed = 1;
this.lottieViewRef.current.play();
this.voleData = await getVoles();
if(this.voleData.length > 0){
this.lastVoleTimestamp = this.voleData[this.voleData.length - 1].createdAt;
}
this.animationSpeed = 0;
this.lottieViewRef.current.reset();
this.refreshing = false;
}
_renderItem = ({item}:any) => (
<VoleCard
voleId={item.voleId}
profileImageURL={item.userImageUrl}
userHandle={item.userHandle}
userId={item.userId}
voteCountDictionary={item.votingOptionsDictionary}
userVoteOption={item.userVoteOption}
shareStat={item.shareCount}
description={item.voleDescription}
imageUrl={item.imageUrl.length > 0 ? item.imageUrl[0] : null} //only one image for now
videoUrl={item.videoUrl.length > 0 ? item.videoUrl[0] : null} //only one video for now
time={convertTime(item.createdAt)}
key={JSON.stringify(item)}
/>
);
onScroll(event:any) {
const { nativeEvent } = event;
const { contentOffset } = nativeEvent;
const { y } = contentOffset;
this.offsetY = y;
if(y < -45){
this.animationSpeed = 1;
this.lottieViewRef.current.play();
}
}
onRelease = async () => {
if (this.offsetY <= -45 && !this.refreshing) {
this.flatListRef.current.scrollToOffset({ animated: false, offset: -40 });
hapticFeedback();
this.extraPaddingTop = 40;
this.newVoleData = [1];
this.refreshing = true;
this.animationSpeed = 1;
this.lottieViewRef.current.play();
this.voleData = await getVoles();
this.extraPaddingTop = 0;
this.animationSpeed = 0;
this.lottieViewRef.current.reset();
if(this.voleData.length > 0){
this.lastVoleTimestamp = this.voleData[this.voleData.length - 1].createdAt;
}
this.refreshing = false;
}
}
render() {
return (
<View>
<LottieView
style={styles.lottieView}
ref={this.lottieViewRef}
source={require('../../../assets/loadingDots.json')}
speed={this.animationSpeed}
/>
<FlatList
contentContainerStyle={styles.mainContainer}
data={this.voleData}
renderItem={this._renderItem}
onScroll={(evt) => this.onScroll(evt)}
scrollEnabled={!this.refreshing}
ref={this.flatListRef}
onResponderRelease={this.onRelease}
ListHeaderComponent={(
<View style={{ paddingTop: this.extraPaddingTop}}/>
)}
ListFooterComponent={this.loadingMoreRefreshing ? <ActivityIndicator style={styles.footer}/> : this.refreshing ? null : <Text style={styles.noMoreVolesText}>No more voles</Text>}
onEndReached={this.newVoleData.length > 0 ? this.loadMoreVoles : null}
onEndReachedThreshold={2}
keyExtractor={item => item.voleId}
/>
<StatusBar barStyle={'dark-content'}/>
</View>
)
}
}
const styles = StyleSheet.create({
mainContainer:{
marginTop: 6,
marginLeft: 6,
marginRight: 6,
},
footer:{
marginBottom: 10,
alignSelf:'center'
},
noMoreVolesText:{
fontSize: 10,
marginBottom: 10,
alignSelf:'center',
color:'#000000',
opacity: .5,
},
lottieView: {
height: 50,
position: 'absolute',
top:0,
left: 0,
right: 0,
},
});
export default VolesFeedScreen;
What i think it's doing is that once on let go of the flatlist, it bounces up past the stop point, which is at an offset of -40 above, before the function onRelease starts. Any help is appreciated!
question from:
https://stackoverflow.com/questions/65910714/react-native-flatlist-custom-refresh-control-with-lottie-is-glitchy 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…