leecade / react-native-swiper

The best Swiper component for React Native.
MIT License
10.42k stars 2.34k forks source link

Images not loading on Android #380

Open arminsal1 opened 7 years ago

arminsal1 commented 7 years ago

The library works perfectly on iOS, but a Swiper of Images on the Android version won't display its images. The code:

<Swiper showsButtons={false} style={{}} loop={true} height={screenWidth} width={screenWidth}
      dot={<View style={{backgroundColor: 'rgba(255,255,255,.7)', width: 5, height: 5, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3}} />}
      activeDot={<View style={{backgroundColor: '#49D2FF', width: 8, height: 8, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3}} />}
      paginationStyle={{bottom: 10,}} >
           {finalPhotos.map((item, key) => {
              return (
               <Image key={key} style={{flex:1,width:screenWidth,height:screenWidth,}} source={key === 0 ? (item == "none" ? require("./img/missing-pic-icon.png") : {uri:item}) : {uri:item.image}} />
              );
      })}
</Swiper>

Other details to note: -Once again, there are no issues on iOS -The swiper is contained in a View that's contained in another Swiper -The finalPhotos array is made before returning the overall render function

jackuhan commented 7 years ago

same in flatlist on Android. but not in flatlist on iOS.

arminsal1 commented 7 years ago

I found a workaround for this bug by following the second answer to this question on StackOverflow: https://stackoverflow.com/questions/30626030/can-you-force-a-react-component-to-rerender-without-calling-setstate

I used setTimeout for 100 milliseconds in the ComponentDidMount function to execute the setState. The solution will refresh the Swiper so that the images appear on Android without having to re-render everything.

Psiiirus commented 7 years ago

FYI: i've fixed it by just add an unique key to my swiper ``

``

ayACEP commented 7 years ago

@MM-Psiiirus but after reload, it hide again...

Psiiirus commented 7 years ago

@ayACEP odd maybe it is your content? ...the key={myUniqueId} should force a total rerendering which should solve the "bug".

LEEY19 commented 7 years ago

@MM-Psiiirus @arminsal1 i tried the suggested solution but it didn't work for me. So what happens is that when I load quite a lot of images (say 5 and more), some images get displayed and some don't. My codes:

        <Modal
          animationType={"slide"}
          transparent={false}
          visible={this.state.modalVisible}
          onRequestClose={() => {
            this.setState({modalVisible: false});
          }}
          >
          <Swiper key={this.state.swiper_key} showsButtons={true}>
            {this.state.chosen_image.map((image, i) => 
              this.renderSwiperView(image, i)
            )}
          </Swiper>
        </Modal>
  renderSwiperView(image, key) {
    return (
      <View style={{flex: 1}} key={key}>
        <PhotoView
          key={key}
          source={{uri: image.path}}
          minimumZoomScale={1}
          maximumZoomScale={3}
          onLoad={() => console.log("Image loaded!")}
          resizeMode={'contain'}
          style={{flex: 1}} />
      </View>
    );
  }

Right after I loaded the state variable 'chosen_image' with array of images, I use this.setState({swiper_key: Math.random()}) to re-render the swiper. However, some images fail to display

dzpt commented 7 years ago

This stupid error still exists today on Android

dzpt commented 7 years ago

@arminsal1 setTimeOut 100ms didn't work, because it depends on how many time it take to load the view.

gocampos commented 7 years ago

after 2 days stuck at this issue, I had success when added the same images of "app/images" directory in the "android/app/src/main/res/drawable-mdpi/" path with the prefix "appimages". So: app/images/test.png was also added at android/app/src/main/res/drawable-mdpi/app_images_test.png and it worked

DucAnhPhi commented 7 years ago

What worked for me was to add a condition to the Swiper, making sure that the array you want to render was already created. For example in the render function: { !!this.props.imageArray.length && <Swiper /> }

huyhai commented 6 years ago

+1, same here, any solution?

haseebnaseem commented 6 years ago

same problem, any solution ?

sledderGIT commented 6 years ago

I have the same issue on the Android.

42void commented 6 years ago

+1

bhargav-bkpatel commented 6 years ago

I had to add a delay to get mine to work, but yes it works!

  constructor(props) {
    super(props);
    this.state = { showSwiper: false };
  }

  componentDidMount() {
    // Must use this 100-ms delayed swiper workaround to render on Android properly
    setTimeout(() => {
      this.setState({showSwiper: true});
    }, 100);
  }

  render() {
    var exampleSwiper = (
      <Swiper activeDotColor={'white'} loop={false} >
        <View style={{width: 100, height: 100, backgroundColor: 'white'}} />
        <View style={{width: 100, height: 100, backgroundColor: 'white'}} />
        <View style={{width: 100, height: 100, backgroundColor: 'white'}} />
      </Swiper>
    );
    return (
      <Modal presentationStyle={'overFullScreen'}>
        {this.state.showSwiper ? exampleSwiper : null}
      </Modal>
    );
  }