Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RefreshControl with ScrollView moves screen content down with each refresh

I've got a screen with a ScrollView that has a refreshControl property. Turns out that when I refresh my screen, the whole content of the screen moves a few positions down. If I refresh again it keeps going down and so on.

enter image description here enter image description here

This screenshots are taken right before refreshing and right after. As you see after refreshing some space was added on top of the screen. Why?

Here's what's inside my render function:

render() {
  if(this.state.isLoading || this.state.user === null) {
   // IF I PUT RETURN NULL HERE IT WORKS FINE,AND THE CONTENT DOESNT GO DOWN
    return(<ScrollView contentContainerStyle={{alignItems: "center", flex: 1, justifyContent: 'center'}}>
      <Spinner isVisible={true} size={100} type={'Pulse'} color={'#013773'}/>
      <DropdownAlert ref={ref => this.dropDownAlertRef = ref} /> 
    </ScrollView>);
  }
  else {
    return (
      <ScrollView
      refreshControl={
        <RefreshControl
          refreshing={this.state.isLoading}
          onRefresh={this._onRefresh.bind(this)}
        />
      }>
        <View style={styles.whiteContainer}>
          <View style={{backgroundColor: colors.white,paddingVertical: 10, borderStyle: 'solid', borderColor: colors.black}}>
              <Text style={{fontStyle: 'italic', fontWeight: 'bold', fontSize:20, marginLeft:20, color: colors.grey}}>
                Mis donaciones
              </Text>
          </View>
          {this.state.myDonations.length > 0 ? 
          <Carousel
            ref={(c) => { this._carousel = c; }}
            data={this.state.myDonations}
            renderItem={this._renderDonation}
            sliderWidth={SLIDER_WIDTH}
            itemWidth={ITEM_WIDTH2}
            inactiveSlideShift={0}
            onSnapToItem={(index) => this.setState({ index })}
            scrollInterpolator={scrollInterpolator}
            slideInterpolatedStyle={animatedStyles}
            useScrollView={true}
            />: 
            <Text style={{fontStyle: 'italic', alignSelf: 'center', fontWeight: 'bold', fontSize:20, marginTop:20, marginBottom: 40, color: colors.grey}}>
            ¡Nada para mostrar!
          </Text>}
        </View>
        {this.state.user.category === "Voluntario" ? 
        <View style={styles.whiteContainer2}>
        <View style={{backgroundColor: colors.white,paddingVertical:10, borderStyle: 'solid', borderColor: colors.black}}>
            <Text style={{fontStyle: 'italic', fontWeight: 'bold', fontSize:20, marginLeft:20, color: colors.grey}}>
              Mis entregas
            </Text>
        </View>
        {this.state.myDeliveries.length > 0 ? 
        <Carousel
        ref={(c) => { this._carousel = c; }}
        data={this.state.myDeliveries}
        renderItem={this._renderDelivery}
        sliderWidth={SLIDER_WIDTH}
        itemWidth={ITEM_WIDTH2}
        inactiveSlideShift={0}
        onSnapToItem={(index) => this.setState({ index })}
        scrollInterpolator={scrollInterpolator}
        slideInterpolatedStyle={animatedStyles}
        useScrollView={true}
      /> : <Text style={{fontStyle: 'italic', alignSelf: 'center', fontWeight: 'bold', fontSize:20, marginTop:20, marginBottom: 40, color: colors.grey}}>
      ¡Nada para mostrar!
    </Text>}
      </View>
        : null}
        <View style={styles.whiteContainer2}>
          <View style={{backgroundColor: colors.white, paddingVertical:10, borderStyle: 'solid', borderColor: colors.black}}>
              <Text style={{fontStyle: 'italic', fontWeight: 'bold', fontSize:20, marginLeft:20, color: colors.grey}}>
                Pedidos
              </Text>
          </View>
          {this.state.requests.length > 0 ? 
          <Carousel
              ref={(c) => { this._carousel = c; }}
              data={this.state.requests}
              renderItem={this._renderRequest}
              sliderWidth={SLIDER_WIDTH}
              itemWidth={ITEM_WIDTH}
              inactiveSlideShift={0}
              onSnapToItem={(index) => this.setState({ index })}
              scrollInterpolator={scrollInterpolator}
              slideInterpolatedStyle={animatedStyles}
              useScrollView={true}
            /> : <Text style={{fontStyle: 'italic', alignSelf: 'center', fontWeight: 'bold', fontSize:20, marginTop:20, marginBottom: 40, color: colors.grey}}>
            ¡Nada para mostrar!
          </Text>}
        </View>
        <DropdownAlert ref={ref => this.dropDownAlertRef = ref} /> 
      </ScrollView>
    );
  }
}

_onRefresh looks like this:

_onRefresh = () => {   
  this.setState({
    user: null,
    isLoading: true
  });
}

isLoading is later set on false when methods inside componentDidUpdate finish loading.

I'm importing RefreshControl and ScrollView from "react-native": "~0.61.4".

Update: As you see inside my render method I got an if-else statement. Turns out if I put return null instead of my spinner inside of the first block, the problem is solved. Why?

like image 500
Flama Avatar asked Apr 05 '26 15:04

Flama


1 Answers

Ok, I found the issue. As you see I had a conditional if-else statement in my render method. Turns out I had to add RefreshControl to the ScrollView of the first block of the statement as well.

render() {
  if(this.state.isLoading || this.state.user === null) {
    return(
    <ScrollView contentContainerStyle={{alignItems: "center", flex: 1, justifyContent: 'center'}}
    refreshControl={
      <RefreshControl
        refreshing={false}
        onRefresh={this._onRefresh.bind(this)}
      />
    }>
      ...
    </ScrollView>);
  }
  else {
    return (
      <ScrollView
      refreshControl={
        <RefreshControl
          refreshing={this.state.isLoading}
          onRefresh={this._onRefresh.bind(this)}
        />
      }>
        ...
      </ScrollView>
    );
  }
}
like image 98
Flama Avatar answered Apr 08 '26 05:04

Flama