Open hengkx opened 4 years ago
Hey, For now, we don't support this kind of functionality. PR are welcome.
How do we about implementing it customly. This is much required!
I insert the first page to the end of pages aray: const pages = [<Page1 />, <Page2 />, <Page3 />, <Page1 />];
. Then I track selected page using onPageSelected
callback, and when selectedPage >= pages.length - 1
I call pagerViewRef.current?.setPageWithoutAnimation(0);
.
That creates an illusion of infinite scroll, it doesn't work if you want to go swipe back from the first page to see the last, but it must be achievable in the same way, setting the initialPage={1}
.
A proper implementation would be nice though.
To continue of @binchik steps:
const slides = [slide1, slide2, slide3]
const firstSlide = slides[0]
const lastSlide = slides[slides.length - 1]
const loopingSlides = [lastSlide, ...slides, firstSlide]
const viewPagerRef = useRef()
return (
<>
<ViewPager
initialPage={1}
ref={viewPagerRef}
onPageSelected={event => {
const currentPage = event.nativeEvent.position
const reachedFakeLastSlide = currentPage === 0
const reachedFakeFirstSlide = currentPage === loopingSlides.length - 1
if (reachedFakeFirstSlide) {
viewPagerRef.current.setPageWithoutAnimation(1)
} else if (reachedFakeLastSlide) {
viewPagerRef.current.setPageWithoutAnimation(loopingSlides.length - 2)
} else {
setPage(currentPage)
}
}}
style={styles.container}
>
{loopingSlides}
</ViewPager>
<Indicators length={3} active={page - 1} />
</>
)
To continue of @binchik steps:
const slides = [slide1, slide2, slide3] const firstSlide = slides[0] const lastSlide = slides[slides.length - 1] const loopingSlides = [lastSlide, ...slides, firstSlide] const viewPagerRef = useRef() return ( <> <ViewPager initialPage={1} ref={viewPagerRef} onPageSelected={event => { const currentPage = event.nativeEvent.position const reachedFakeLastSlide = currentPage === 0 const reachedFakeFirstSlide = currentPage === loopingSlides.length - 1 if (reachedFakeFirstSlide) { viewPagerRef.current.setPageWithoutAnimation(1) } else if (reachedFakeLastSlide) { viewPagerRef.current.setPageWithoutAnimation(loopingSlides.length - 2) } else { setPage(currentPage) } }} style={styles.container} > {loopingSlides} </ViewPager> <Indicators length={3} active={page - 1} /> </> )
There is no example for loop implementation with this component. I tried to apply this code to my project, but I couldn't run. Any idea?
render() {
const slides = this.state.slideData;
const viewPagerRef = useRef<Container2 | null>(null);
const firstSlide = slides[0]
const lastSlide = slides[slides.length - 1]
const loopingSlides = [lastSlide, ...slides, firstSlide]
const Container2 = styled(PagerView)`
height: ${height}px;
width: 100%;
`
<Container2
orientation='horizontal'
initialPage={1}
onPageSelected={(e) => {
const currentPage = e.nativeEvent.position
const reachedFakeLastSlide = currentPage === 0
const reachedFakeFirstSlide = currentPage === loopingSlides.length - 1
if (reachedFakeFirstSlide) {
viewPagerRef.current.setPageWithoutAnimation(1)
} else if (reachedFakeLastSlide) {
viewPagerRef.current.setPageWithoutAnimation(loopingSlides.length - 2)
}
this.setState({ selectedd: e.nativeEvent.position })
// console.log(this.state.selectedd);
// alert('aaas')
}
}
ref={viewPagerRef}>
{item.subdata.map((subitem, indexx) => {
return (
<View key={indexx} style={{ justifyContent: 'center', width: '100%', }}>
@binchik it's not good, it will cause blink
I did a investigation and it should be implemented using below tutorials/code:
iOS: https://github.com/igroomgrim/Infinite-scroll-with-uipageviewcontroller
Those who are looking for infinite loop function. Check this https://github.com/computerjazz/react-native-infinite-pager.
This is super important and needed solution for our app as well, any help from be super appreciated
Still can't use this library without infinite scroll :(
A solution
To summarize (without considering specific cases):
2
you know user is going forward0
you know user is going backwardconst VirtualPagerView = ({
onPageSelected,
initialPage = 0,
pages,
pageComponent: PageComponent,
...props
}) => {
const ref = useRef()
const [offset, setOffset] = useState(initialPage)
return (
<PagerView
{...props}
initialPage={initialPage}
ref={(pager) => {
ref.current = {
...pager,
setPage: (page) => {
setOffset(page ? page + 1 : 0)
pager.setPageWithoutAnimation(0)
}
}
}}
onPageSelected={e => {
const position = e.nativeEvent.position
if (position === 1) {
if (offset === 0) {
setOffset(1)
if (typeof onPageSelected === 'function') {
onPageSelected(1)
}
}
return
}
setOffset(value => {
const offset = Math.max(0, position ? value + 1 : value - 1)
if (offset) {
ref.current.setPageWithoutAnimation(1)
}
if (typeof onPageSelected === 'function') {
onPageSelected(offset)
}
return offset
})
}}
>
{pages.slice(Math.max(0, offset - 1), Math.max(3, offset + 2)).map((page, index) => (
<PageComponent key={page.key} {...page} />
))}
</PagerView>
)
})
Usage
<VirtualPagerView
onPageSelected={position => {
console.log(`Page ${position} selected`)
}}
pages={[{ key: 1, name: 'A' }, { key: 2, name: 'B' }, { key: 3, name: 'C' }, { key: 4, name: 'D' }, { key: 5, name: 'E' }, { key: 6, name: 'F' }]}
pageComponent={({ name }) => (
<View>
<Text>{name}</Text>
</View>
)}
/>
As dev, I would like to have ability to have infinite scroll behavior.