I have been developing a personal application to build a finance app. At the moment I'm creating an Onboarding screen, with is successfully working. Although I want to add some styles to it, I have created an animated paginator, but I want to make the last page indicator turn into a Touchable button.
At the moment the paginator looks like this:
I want that last animation turn into a button.
This is my code for Paginator:
import React from 'react';
import {
Container,
CurrentSelectedPageIndicator,
ButtonContainer
} from './styles';
import { useWindowDimensions } from 'react-native';
interface PaginatorProps {
data: any;
scrollX: any;
currentIndex: any;
}
export function Paginator({ data, scrollX, currentIndex }: PaginatorProps){
const { width } = useWindowDimensions();
return (
<Container>
{data.map((_: any, index: any) => {
const inputRange = [(index - 1) * width, index * width, (index + 1) * width];
let dotWidth = scrollX.interpolate({
inputRange,
outputRange: [10, 20, 10],
extrapolate: 'clamp'
});
const opacity = scrollX.interpolate({
inputRange,
outputRange: [0.3, 1, 0.3],
extrapolate: 'clamp'
});
if (currentIndex.toString() === '2') {
dotWidth = scrollX.interpolate({
[1,2,3],
outputRange: [10, 20, 10],
extrapolate: 'clamp'
});
}
return <CurrentSelectedPageIndicator key={index.toString()} style={{ width: dotWidth, opacity }} />;
})}
</Container>
);
}
Styles:
import { RFValue } from "react-native-responsive-fontsize";
import styled from "styled-components/native";
import { Animated } from 'react-native';
export const Container = styled.View`
flex-direction: row;
height: ${RFValue(64)}px;
`;
export const CurrentSelectedPageIndicator = styled(Animated.View).attrs({
shadowOffset: { width: 1, height: 3 }
})`
shadow-color: ${({ theme }) => theme.colors.text_dark };
elevation: 1;
shadow-opacity: 0.3;
shadow-radius: 1px;
height: ${RFValue(10)}px;
width: ${RFValue(10)}px;
border-radius: 10px;
background-color: ${({ theme }) => theme.colors.blue };
margin-horizontal: ${RFValue(8)}px;
`;
export const ButtonContainer = styled(Animated.View)`
width: 100%;
height: ${RFValue(50)}px;
background-color: ${({ theme }) => theme.colors.blue};
border-radius: 10px;
align-items: center;
justify-content: center;
`;
export const ButtonTitle = styled.Text`
font-family: ${({ theme }) => theme.fonts.medium};
font-size: ${RFValue(14)}px;
color: ${({ theme }) => theme.colors.shapeColor};
`;
I tried implementing this logic, but there was no animation. Of course.
I want it to turn into something like this:
This is the page with calls the paginator:
import React, { useState, useRef } from 'react';
import {
Container,
FlatListContainer
} from './styles';
import {
FlatList,
Animated
} 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 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} currentIndex={currentIndex}/>
</Container>
);
}