Nilton Schumacher F
Nilton Schumacher F

Reputation: 1180

Get the last scroll from a FlatList and redirect

I'm creating an Onboarding screen. I don't want to add buttons to this onboarding screen, the only way to go to the next page is by swiping. Although I need to have a way to get when the user is at the last screen, and when he swipes right, I will be redirecting him to the login screen.

This is the last screen on the app: enter image description here

When the user swipes right from this screen, I want to make a redirect, like a function or a onPress.
This is the onboarding code:

import React, { useState, useRef } from 'react';
import { 
    Container,
    FlatListContainer
} from './styles';
import {
    FlatList,
    Animated,
    TouchableOpacity
} from 'react-native'
import OnboardingData from '../../utils/onboarding';
import { OnboardingItem } from '../../components/OnboardingItem';
import { Paginator } from '../../components/Paginator';

export function Onboarding(){

    const [currentIndex, setCurrentIndex] = useState(0);
    const scrollX = useRef(new Animated.Value(0)).current;
    const scrollY = useRef(new Animated.Value(0)).current;
    const onboardingDataRef = useRef(null);

    const viewableItemsChanged = useRef(({ viewableItems }: any) => {
        setCurrentIndex(viewableItems[0].index);
    }).current;

    const viewConfig = useRef({ viewAreaCoveragePercentThreshold: 50 }).current;

    return (
        <Container>
            <FlatListContainer>
                <FlatList 
                    data={OnboardingData} 
                    renderItem={({ item }) => <OnboardingItem image={item.image} title={item.title} description={item.description}/>}
                    horizontal
                    showsHorizontalScrollIndicator={false}
                    pagingEnabled={true}
                    bounces={false}
                    keyExtractor={(item) => String(item.id)}
                    onScroll={Animated.event([{ nativeEvent: { contentOffset: { x: scrollX } }}], {
                        useNativeDriver: false
                    })}
                    scrollEventThrottle={32}
                    onViewableItemsChanged={viewableItemsChanged}
                    viewabilityConfig={viewConfig}
                    ref={onboardingDataRef}
                />
            </FlatListContainer>

            <Paginator data={OnboardingData} scrollX={scrollX} scrollY={scrollY} currentIndex={currentIndex}/>
        </Container>
    );
}

Upvotes: 0

Views: 937

Answers (1)

PhantomSpooks
PhantomSpooks

Reputation: 3540

I thought about it, and the old method wouldnt work, as there isnt a viewableItem beyond the final page.

You could use the FlatList onScroll function to listen for swipes. When at the final page and a scroll event occurs, verify that it wasnt an attempt to go to the previous page and then navigate. e.g.


// store previous scroll values
const prevScroll = useRef({});

// scrollX, scrollY already contains the data 
useEffect(()=>{
  let isLastIndex = currentIndex == onBoardingData.length  - 1;
  let isScrollingToNextPage =  scrollX > prevScroll.current.x
  if( isLastIndex && isScrollingToNextPage ){ 
      props.navigation.navigate("Login");
      return
    }
  // store offsets
  prevScroll.current = { x:scrollX, y:scrollY}
},[scrollX, scrollY])

If you would like for the old method to work you could just add an additional page (could be an empty view or a view with a small message)

--------OLD--------

Im assuming that OnBordingData is an array since you're passing it to the Flatlist data prop. If so, then couldnt you add a conditional to your viewableItemsChanged so that it goes to the login screen when at index > OnBoardingData.length - 1? e.g

const viewableItemsChanged = useRef(({ viewableItems }: any) => {
        const index = viewableItems[0].index;
        if(index >= OnBoardinData.length -1){
          // be sure to add props as a parameter to OnBoarding function
          props.navigation.navigate("Login");
          return
        } 
        setCurrentIndex(index);
    }).current;

--------OLD--------

Upvotes: -1

Related Questions