leecade / react-native-swiper

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

Pagination dot is not moving on both android and ios #1273

Open ArkaneKhan opened 3 years ago

ArkaneKhan commented 3 years ago

Version Which versions are you using:

Expected behaviour pagination dot should move on swiping to next item

Actual behaviour pagination dot are not moving on swiping to next item. Some time it works some time it stays stuck at 0 position.

How to reproduce it <Swiper height={Metrics.heightRatio(320)} containerStyle={styles.swiper} style={styles.swiper} loop={false} dotColor={Colors.primary.white} dotStyle={{opacity: 0.4}} activeDotColor={Colors.primary.white}

{data.map((item) => ( <ImageHandler key={fast-${item.id}} source={{uri: item.path}} style={styles.profileImg} thumb={item.thumb} /> ))}

chiubaka commented 3 years ago

I'm noticing something similar to this, and in my case I'm pretty sure the dots stay stuck if the Swiper is not initially visible in the view. Anytime the Swiper is initially visible, it works fine. But in cases where it was made visible, the indexes don't work and the index change callbacks don't fire.

chiubaka commented 3 years ago

Ah, just kidding. It's because I was accidentally dynamically switching between a swiper with a single child to a swiper with many children. Seems like the number of children cannot / should not change dynamically. In my case because it started with a single child, the swiper continued to behave as if it had just a single child even though it now had many more.

ArkaneKhan commented 3 years ago

so does the dot works fine with many childs?

chiubaka commented 3 years ago

It works fine with many children. It just needs to be initialized with that number of children.

M46N3 commented 3 years ago

I can confirm the behavior @chiubaka describes. The pagination dot is only stuck on the first one if the swiper was initiated with only one child. For my use case I need to change the content of the swiper dynamically. Does anyone have a workaround to make that work properly?

ArkaneKhan commented 3 years ago

updateIndex = (offset, dir, cb) => { const state = this.state // Android ScrollView will not scrollTo certain offset when props change let index = state.index if (!this.internals.offset) // Android not setting this onLayout first? https://github.com/leecade/react-native-swiper/issues/582 this.internals.offset = {} const diff = offset[dir] - this.internals.offset[dir] const step = dir === 'x' ? state.width : state.height let loopJump = false

// added this line on library to make it work for dynamic childrens.
this.setState({index: offset.x / state.width});
Saqib92 commented 3 years ago

Ah, just kidding. It's because I was accidentally dynamically switching between a swiper with a single child to a swiper with many children. Seems like the number of children cannot / should not change dynamically. In my case because it started with a single child, the swiper continued to behave as if it had just a single child even though it now had many more.

In my case I don't know how many slides will come from API. it could be 2 or it could be 50..! How can I initialized it??

ycdaskin commented 2 years ago

I am fetching online data to fill swiper elements. Because the component has no data when it renders swiper doesn't work properly. Dots stack, loop doesn't work etc. In my project i show "announcements" in my swiper and my solution is rendering the swiper after i fetch "announcements":

{announcements !== null &&
                                <Swiper
                                    autoplay
                                    showsButtons
                                >
                                    {announcements.map((item) => (        
                                                <TouchableOpacity
                                                    style={styles.eventImage}
                                                    onPress={() => handleEventSelected(item)} //Linking.openURL(item.target)
                                                >
                                                    <Image
                                                        source={{ uri: item.banner.url }}
                                                        style={{ width: undefined, height: undefined, flex: 1 }}
                                                        resizeMode='cover'
                                                    />
                                                    <Text
                                                        style={{
                                                            fontSize: 24,
                                                            color: 'wheat',
                                                            position: 'absolute',
                                                            top: 15,
                                                            left: 15,
                                                            textShadowColor: 'black',
                                                            textShadowRadius: 2
                                                        }}
                                                    >
                                                        {item.name}
                                                    </Text>
                                                </TouchableOpacity>

                                        ))
                                    }
                                </Swiper>
                            }
Saqib92 commented 2 years ago

I am fetching online data to fill swiper elements. Because the component has no data when it renders swiper doesn't work properly. Dots stack, loop doesn't work etc. In my project i show "announcements" in my swiper and my solution is rendering the swiper after i fetch "announcements":

{announcements !== null &&
                                <Swiper
                                    autoplay
                                    showsButtons
                                >
                                    {announcements.map((item) => (        
                                                <TouchableOpacity
                                                    style={styles.eventImage}
                                                    onPress={() => handleEventSelected(item)} //Linking.openURL(item.target)
                                                >
                                                    <Image
                                                        source={{ uri: item.banner.url }}
                                                        style={{ width: undefined, height: undefined, flex: 1 }}
                                                        resizeMode='cover'
                                                    />
                                                    <Text
                                                        style={{
                                                            fontSize: 24,
                                                            color: 'wheat',
                                                            position: 'absolute',
                                                            top: 15,
                                                            left: 15,
                                                            textShadowColor: 'black',
                                                            textShadowRadius: 2
                                                        }}
                                                    >
                                                        {item.name}
                                                    </Text>
                                                </TouchableOpacity>

                                        ))
                                    }
                                </Swiper>
                            }

Try something like: const [slides, setSlides] = useState(['', '', '']);

bolingsun commented 2 years ago

{ bannerList.length ? this.renderBanner(bannerList) : undefined }

if fetching online data to fill swiper elements, the render must after the got the data

so if render the Swiper, need make a judgement at first

中文翻译:

如果填充轮播图的内容,是在获取数据后。那么,渲染轮播图组件的时候,需要加个逻辑判断。不能是空数组map渲染出来,否则,指示器就不能滑动,永远激活在第一个。

huuanhopp commented 2 years ago
        paginationStyle={{position: 'absolute', bottom: 1}}