Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
222 views
in Technique[技术] by (71.8m points)

React Native Flatlist custom refresh control with Lottie is glitchy

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...