React Navigation: How to put an iOS style dismissible bar on expo modal

Viewed 420

I am trying to achieve a dismissible bar for my modal. Something like in this image:

enter image description here

What i am at right now

enter image description here

code:

 <RootStack.Group
     screenOptions={{
       presentation: "modal",
       gestureEnabled: true,
       headerBackTitleVisible: false,
       headerTitle: "",
       hideNavigationBar: false,
       gestureEnabled: true,
     }}
   >
     <RootStack.Screen name="MyModal" component={ModalScreen} />
  </RootStack.Group>
2 Answers

I am not sure if there is a built-in solution to that, but for sure you can hide the status bar per screen. In this case that's MyModal screen. And once you hide it you can implement a custom header that can be anything you wish it to be, but you will need to hook back actions etc.

Another way is to implement a custom Header, React Navigation has an API for that https://reactnavigation.org/docs/stack-navigator#header

Since there isn't a built in solution, you could achieve what you want by doing something like so:

(1) You will need to replace react-navigation's generated header with a custom one, like the following:

function LogoTitle() {
  return (
    <Image
      style={{ width: 50, height: 50 }}
      source={require('@expo/snack-static/react-native-logo.png')}
    />
  );
}

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ headerTitle: (props) => <LogoTitle {...props} /> }}
      />
    </Stack.Navigator>
  );
}

Source: https://reactnavigation.org/docs/headers#replacing-the-title-with-a-custom-component

(2) Your custom component would have to look something like this:

export default function App() {
  const cancelButtonOnPress = () => {
    navigation.goBack();
  }

  return (
    <View style={styles.container}>
      <View style={styles.bar}></View>
      <Text onPress={()=>{cancelButtonOnPress()}} style={styles.cancelButton}>Cancel</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  cancelButton: {
    color: '#0573ad'
  },
  bar: {
    alignSelf: 'center',
    width: 40,
    height: 7,
    backgroundColor: 'gray',
    borderRadius: 40,
  },
  container: {
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    padding: 8,
    borderWidth: 1,
    borderColor: 'black',
  },
});

The above App looks like the following: enter image description here

(3) Since you are passing your custom component to react-navigation, the gesture swipe to dismiss the modal should be retained, if for some reason it isn't, you could try setting fullScreenGestureEnabled to true in screenOptions.

Related