Created
January 23, 2021 18:52
-
-
Save mattThousand/6203be7e18f37a9bb8c5e70e6bce4ad6 to your computer and use it in GitHub Desktop.
Tapping an individual dot animates the flatlist's scroll position.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, {FunctionComponent, useRef} from 'react'; | |
| import { | |
| Animated, | |
| Dimensions, | |
| FlatList, | |
| Image, | |
| Pressable, | |
| StyleSheet, | |
| View, | |
| } from 'react-native'; | |
| const images: string[] = [ | |
| 'https://media.tenor.com/images/3704f2b9b8b66a5747116f436a5e6aba/tenor.gif', | |
| 'https://media.tenor.com/images/78feaf65c477ead06981dca74c3ead14/tenor.gif', | |
| 'https://media.tenor.com/images/425213c8ada06900931c2d0213389ae4/tenor.gif', | |
| ]; | |
| const {width} = Dimensions.get('screen'); | |
| const CustomPageControl: FunctionComponent = () => { | |
| const animatedValue = useRef(new Animated.Value(0)).current; | |
| const flatListRef = useRef<FlatList>(); | |
| const handleDotPress = (index) => { | |
| flatListRef.current.scrollToIndex({animated: true, index}); | |
| }; | |
| return ( | |
| <View style={style.container}> | |
| <View style={style.topContainer}> | |
| <FlatList | |
| ref={flatListRef} | |
| data={images} | |
| horizontal | |
| showsHorizontalScrollIndicator={false} | |
| onScroll={Animated.event( | |
| [{nativeEvent: {contentOffset: {x: animatedValue}}}], | |
| {useNativeDriver: false}, | |
| )} | |
| pagingEnabled={true} | |
| keyExtractor={(_, index) => index.toString()} | |
| renderItem={({item}) => { | |
| return ( | |
| <View style={style.imageContainer}> | |
| <Image style={style.image} source={{uri: item}} /> | |
| </View> | |
| ); | |
| }} | |
| /> | |
| </View> | |
| <View style={style.bottomContainer}> | |
| <FlatList | |
| horizontal | |
| data={images} | |
| keyExtractor={(_, index) => index.toString()} | |
| renderItem={({index}) => { | |
| const inputRange = [ | |
| (index - 1) * width, | |
| index * width, | |
| (index + 1) * width, | |
| ]; | |
| const colorOutputRange = ['#000', 'cyan', '#000']; | |
| const scaleOutputRange = [1, 2, 1]; | |
| const dotScale = animatedValue.interpolate({ | |
| inputRange, | |
| outputRange: scaleOutputRange, | |
| extrapolate: 'clamp', | |
| }); | |
| const color = animatedValue.interpolate({ | |
| inputRange, | |
| outputRange: colorOutputRange, | |
| extrapolate: 'clamp', | |
| }); | |
| return ( | |
| <View style={style.dotContainer}> | |
| <PagingDot | |
| index={index} | |
| onPress={handleDotPress} | |
| color={color} | |
| scale={dotScale} | |
| /> | |
| </View> | |
| ); | |
| }} | |
| /> | |
| </View> | |
| </View> | |
| ); | |
| }; | |
| const PagingDot: FunctionComponent<{scale; color; index; onPress}> = ({ | |
| scale, | |
| color, | |
| index, | |
| onPress, | |
| }) => { | |
| return ( | |
| <Pressable onPress={() => onPress(index)}> | |
| <Animated.View | |
| style={[ | |
| style.pagingDot, | |
| {backgroundColor: color, transform: [{scale}]}, | |
| ]} | |
| /> | |
| </Pressable> | |
| ); | |
| }; | |
| const style = StyleSheet.create({ | |
| container: { | |
| flex: 3, | |
| }, | |
| topContainer: { | |
| flex: 2, | |
| }, | |
| bottomContainer: { | |
| flex: 1, | |
| width, | |
| justifyContent: 'flex-start', | |
| alignItems: 'center', | |
| }, | |
| imageContainer: { | |
| justifyContent: 'flex-end', | |
| paddingBottom: 40, | |
| alignItems: 'center', | |
| width, | |
| }, | |
| image: { | |
| width: width - 80, | |
| height: 300, | |
| borderRadius: 40, | |
| }, | |
| pagingDot: { | |
| width: 14, | |
| height: 14, | |
| backgroundColor: 'cyan', | |
| borderRadius: 7, | |
| borderWidth: 2, | |
| borderColor: '#000', | |
| }, | |
| dotContainer: { | |
| width: 50, | |
| padding: 10, | |
| }, | |
| }); | |
| export default CustomPageControl; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment