Skip to content

Instantly share code, notes, and snippets.

@flunder
Created January 11, 2023 14:53
Show Gist options
  • Save flunder/93d2ab40cf3be4aa52d0ad5b645bf578 to your computer and use it in GitHub Desktop.
Save flunder/93d2ab40cf3be4aa52d0ad5b645bf578 to your computer and use it in GitHub Desktop.
Fake Draggable Sheet with Snapping
import React, { useRef, useState } from 'react';
import { Animated, FlatList, StyleSheet } from 'react-native';
import { Box, Button, Text, Touchable } from '@app/components';
import { Colors, Grid, Sizes } from '@app/utils/const/theme';
import { viewPort } from '@app/utils';
const initialPosition = viewPort.height.full - 300;
const MapSheet = ({
children,
debug,
}: {
children: React.ReactElement;
debug?: boolean;
}) => {
const flatlistRef = useRef<FlatList>(null);
const scrollOffsetY = useRef(new Animated.Value(0)).current;
const [fullScreen, setFullscreen] = useState(false);
const translateY = scrollOffsetY.interpolate({
inputRange: [0, 250],
outputRange: [initialPosition, 0],
extrapolate: 'clamp',
});
const viewabilityConfig = useRef({ itemVisiblePercentThreshold: 75 }).current;
const onViewableItemsChanged = useRef(({ viewableItems }) => {
if (viewableItems.length > 0) {
if (viewableItems?.[0].item === 2) setFullscreen(true);
if (viewableItems?.[0].item === 1) setFullscreen(false); // Bugfix
}
}).current;
const goFullScreen = () => {
flatlistRef.current?.scrollToIndex({ index: 1, animated: true });
};
const returnToBeginning = () => {
flatlistRef.current?.scrollToIndex({ index: 0, animated: true });
setFullscreen(false);
};
const renderItem = ({ index }) => {
return (
<Touchable
width="100%"
height={viewPort.height.full - 300}
onPress={goFullScreen}
opacity={debug ? 0.5 : 0}
backgroundColor={debug ? (index === 1 ? 'blue' : 'red') : 'transparent'}
activeOpacity={0.5}
/>
);
};
return (
<Animated.View
style={{
flex: 1,
backgroundColor: Colors.white,
alignItems: 'center',
transform: [{ translateY }],
}}
>
<Box
width={60}
height={5}
backgroundColor={Colors.gray400}
borderRadius={100}
marginTop={Sizes[3]}
/>
{children}
<Animated.FlatList
ref={flatlistRef}
data={[1, 2]}
pointerEvents={fullScreen ? 'none' : 'auto'}
renderItem={renderItem}
scrollEventThrottle={16}
decelerationRate="fast"
snapToInterval={250}
onViewableItemsChanged={onViewableItemsChanged}
viewabilityConfig={viewabilityConfig}
showsVerticalScrollIndicator={false}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollOffsetY } } }],
{ useNativeDriver: true }
)}
style={StyleSheet.absoluteFillObject}
/>
<Button
size="sm"
position="absolute"
bottom={Sizes[6]}
onPress={returnToBeginning}
>
Map
</Button>
</Animated.View>
);
};
export { MapSheet };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment