Skip to content

Commit 5bbd6d3

Browse files
Merge pull request #13 from mtzfactory/main
Implement dynamic content snapPoints
2 parents b0cc729 + 0cea000 commit 5bbd6d3

File tree

3 files changed

+83
-29
lines changed

3 files changed

+83
-29
lines changed

example/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
"dependencies": {
1515
"@gorhom/bottom-sheet": "^4.3.1",
1616
"@react-navigation/native": "^6.0.10",
17-
"expo": "^45.0.5",
18-
"react": "17.0.2",
19-
"react-dom": "17.0.2",
20-
"react-native": "0.68.2",
21-
"react-native-gesture-handler": "~2.2.1",
22-
"react-native-reanimated": "~2.8.0",
23-
"react-native-web": "0.17.7"
17+
"expo": "^46.0.9",
18+
"react": "18.0.0",
19+
"react-dom": "18.0.0",
20+
"react-native": "0.69.6",
21+
"react-native-gesture-handler": "2.5.0",
22+
"react-native-reanimated": "2.9.1",
23+
"react-native-web": "0.18.7"
2424
},
2525
"devDependencies": {
2626
"@babel/core": "~7.18.2",

example/src/SimpleExample.tsx

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { Button, StyleSheet, Text, View } from 'react-native';
1313
type BottomSheetParams = {
1414
Home: undefined;
1515
Sheet: { id: number };
16+
BigSheet: { id: number };
1617
};
1718

1819
const BottomSheet = createBottomSheetNavigator<BottomSheetParams>();
@@ -23,12 +24,20 @@ function HomeScreen({
2324
return (
2425
<View style={styles.container}>
2526
<Text>Home Screen</Text>
27+
<View style={styles.spacer} />
2628
<Button
2729
title="Open sheet"
2830
onPress={() => {
2931
navigation.navigate('Sheet', { id: 1 });
3032
}}
3133
/>
34+
<View style={styles.spacer} />
35+
<Button
36+
title="Open a big sheet"
37+
onPress={() => {
38+
navigation.navigate('BigSheet', { id: 1 });
39+
}}
40+
/>
3241
</View>
3342
);
3443
}
@@ -38,46 +47,53 @@ function SheetScreen({
3847
navigation,
3948
}: BottomSheetScreenProps<BottomSheetParams, 'Sheet'>) {
4049
return (
41-
<View style={styles.container}>
50+
<View style={[styles.container, styles.content]}>
4251
<Text>Sheet Screen {route.params.id}</Text>
52+
<View style={styles.spacer} />
4353
<Button
4454
title="Open new sheet"
4555
onPress={() => {
4656
navigation.navigate('Sheet', { id: route.params.id + 1 });
4757
}}
4858
/>
59+
<View style={styles.spacer} />
4960
<Button
50-
title="Close sheet"
61+
title="Open new big sheet"
5162
onPress={() => {
52-
navigation.goBack();
63+
navigation.navigate('BigSheet', { id: route.params.id + 1 });
5364
}}
5465
/>
66+
<View style={styles.spacer} />
5567
<Button
56-
title="Snap to top"
68+
title="Close this sheet"
5769
onPress={() => {
58-
navigation.snapTo(1);
70+
navigation.goBack();
5971
}}
6072
/>
73+
{route.name === ('BigSheet' as unknown) && (
74+
<>
75+
<View style={styles.spacer} />
76+
<Button
77+
title="Snap to top"
78+
onPress={() => {
79+
navigation.snapTo(1);
80+
}}
81+
/>
82+
</>
83+
)}
6184
</View>
6285
);
6386
}
6487

88+
const renderBackdrop = (props: BottomSheetBackdropProps) => (
89+
<BottomSheetBackdrop {...props} appearsOnIndex={0} disappearsOnIndex={-1} />
90+
);
91+
6592
export function SimpleExample() {
66-
const renderBackdrop = React.useCallback(
67-
(props: BottomSheetBackdropProps) => (
68-
<BottomSheetBackdrop
69-
{...props}
70-
appearsOnIndex={0}
71-
disappearsOnIndex={-1}
72-
/>
73-
),
74-
[],
75-
);
7693
return (
7794
<NavigationContainer>
7895
<BottomSheet.Navigator
7996
screenOptions={{
80-
snapPoints: ['70%', '90%'],
8197
backdropComponent: renderBackdrop,
8298
}}
8399
>
@@ -87,11 +103,29 @@ export function SimpleExample() {
87103
component={SheetScreen}
88104
getId={({ params }) => `sheet-${params.id}`}
89105
/>
106+
<BottomSheet.Screen
107+
name="BigSheet"
108+
component={SheetScreen}
109+
options={{
110+
snapPoints: ['50%', '80%'],
111+
}}
112+
getId={({ params }) => `sheet-${params.id}`}
113+
/>
90114
</BottomSheet.Navigator>
91115
</NavigationContainer>
92116
);
93117
}
94118

95119
const styles = StyleSheet.create({
96-
container: { flex: 1, alignItems: 'center', justifyContent: 'center' },
120+
container: {
121+
flex: 1,
122+
alignItems: 'center',
123+
justifyContent: 'center',
124+
},
125+
content: {
126+
marginVertical: 20,
127+
},
128+
spacer: {
129+
margin: 5,
130+
},
97131
});

src/BottomSheetView.tsx

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import {
22
BottomSheetModal,
33
BottomSheetModalProps,
44
BottomSheetModalProvider,
5+
BottomSheetView as RNBottomSheetView,
6+
useBottomSheetDynamicSnapPoints,
57
} from '@gorhom/bottom-sheet';
68
import { ParamListBase, useTheme } from '@react-navigation/native';
79
import * as React from 'react';
@@ -18,8 +20,11 @@ type BottomSheetModalScreenProps = BottomSheetModalProps & {
1820
};
1921

2022
function BottomSheetModalScreen({
21-
navigation,
23+
contentHeight,
24+
handleHeight,
2225
index,
26+
navigation,
27+
snapPoints,
2328
...props
2429
}: BottomSheetModalScreenProps) {
2530
const ref = React.useRef<BottomSheetModal>(null);
@@ -64,22 +69,25 @@ function BottomSheetModalScreen({
6469
return (
6570
<BottomSheetModal
6671
ref={ref}
72+
contentHeight={contentHeight}
73+
handleHeight={handleHeight}
6774
index={index}
75+
snapPoints={snapPoints}
6876
onChange={onChange}
6977
onDismiss={onDismiss}
7078
{...props}
7179
/>
7280
);
7381
}
7482

75-
const DEFAULT_SNAP_POINTS = ['66%'];
76-
7783
type Props = BottomSheetNavigationConfig & {
7884
state: BottomSheetNavigationState<ParamListBase>;
7985
navigation: BottomSheetNavigationHelpers;
8086
descriptors: BottomSheetDescriptorMap;
8187
};
8288

89+
const initialDynamicSnapPoints = ['CONTENT_HEIGHT', 'CONTENT_HEIGHT'];
90+
8391
export function BottomSheetView({ state, descriptors }: Props) {
8492
const { colors } = useTheme();
8593
const themeBackgroundStyle = React.useMemo(
@@ -101,6 +109,14 @@ export function BottomSheetView({ state, descriptors }: Props) {
101109
shouldRenderProvider.current || state.routes.length > 1;
102110

103111
const firstScreen = descriptors[state.routes[0].key];
112+
113+
const {
114+
animatedHandleHeight,
115+
animatedSnapPoints,
116+
animatedContentHeight,
117+
handleContentLayout,
118+
} = useBottomSheetDynamicSnapPoints(initialDynamicSnapPoints);
119+
104120
return (
105121
<>
106122
{firstScreen.render()}
@@ -113,7 +129,7 @@ export function BottomSheetView({ state, descriptors }: Props) {
113129
index,
114130
backgroundStyle,
115131
handleIndicatorStyle,
116-
snapPoints = DEFAULT_SNAP_POINTS,
132+
snapPoints = animatedSnapPoints.value,
117133
...sheetProps
118134
} = options;
119135

@@ -126,6 +142,8 @@ export function BottomSheetView({ state, descriptors }: Props) {
126142
route.snapToIndex ?? index ?? 0,
127143
snapPoints.length - 1,
128144
)}
145+
contentHeight={animatedContentHeight}
146+
handleHeight={animatedHandleHeight}
129147
snapPoints={snapPoints}
130148
navigation={navigation}
131149
backgroundStyle={[themeBackgroundStyle, backgroundStyle]}
@@ -135,7 +153,9 @@ export function BottomSheetView({ state, descriptors }: Props) {
135153
]}
136154
{...sheetProps}
137155
>
138-
{render()}
156+
<RNBottomSheetView onLayout={handleContentLayout}>
157+
{render()}
158+
</RNBottomSheetView>
139159
</BottomSheetModalScreen>
140160
);
141161
})}

0 commit comments

Comments
 (0)