36

Following is my created react native Modal and still couldn't find how to dim the background and transparent around pop-up modal.I am not using any external libraries and trying to find solution without libraries.Is it possible to do with on this way?

enter image description here

My Modal Component

render() {
let modal = this.state.modalType=='skill'? <SkillModal /> : <TrialModal />;
return (
  <View style={styles.container}>
    <Modal
      animationType='slide'
      onRequestClose={() => console.log('no warning')}
      presentationStyle="FormSheet"
      transparent
      visible={this.state.showModal}
    >
      <View>
        <View style={styles.modalView} >
          <TouchableOpacity
            onPress={this.closeModalFunc}
          >
            <Text style={styles.closeText}>X</Text>
          </TouchableOpacity>
          <View>
            {modal}
          </View>
        </View>
      </View>
    </Modal>
  </View>
  );
}

Modal Component Style

import {StyleSheet} from 'react-native';
import colors from '../../../theme/colors';
import metrics from '../../../theme/metrics';
import {container} from '../../../theme/base';

const styles = StyleSheet.create({
container: {
 backgroundColor: colors.background.gray,
},
modalView: {
 backgroundColor: colors.background.white,
 margin: 40,
},
closeText: {
  backgroundColor: colors.background.purpleishBlue,
  color: colors.background.white,
  borderRadius: metrics.avatar.small,
  width: 32,
  padding: 6,
  alignSelf: 'flex-end',
  textAlign: 'center',
  borderWidth: 1,
  borderColor: colors.background.white,
 },
});

export default styles;
Asbar Ali
  • 955
  • 1
  • 13
  • 26

10 Answers10

58

I solve this one by create my own component MyPopup like below

class MyPopup extends React.PureComponent {

render() {
    return (
        <Modal 
            animationType="fade"
            transparent={true}
            visible={this.props.visible}
            >
                <View style={{flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.5)'}}>
                    {this.props.children}
                </View>
        </Modal>
    )
}}

Then I use it like

<MyPopup visible={this.state.modalVisible}>
<View style={{
    width: '90%',
    height: 50,
    borderColor: '#ccc',
    borderWidth: 1,
    borderStyle: 'solid',
    backgroundColor: 'white',
    elevation: 20,
    padding: 10,
    borderRadius: 4,
}}>
    <Text>Hello, This is my model with dim background color</Text>
</View>

mai danh
  • 853
  • 8
  • 14
41

I had the same problem as you and I solved it by setting transparent={true} in the Props of the modal and by setting a 50% transparency in the style of the Modal's main View: backgroundColor: 'rgba(0, 0, 0, 0.5)'

Yassine Letaief
  • 436
  • 4
  • 4
29

You can programmatically set the opacity of your main View when Modal is visible.

<View style={[styles.container, this.state.showModal ? {backgroundColor: 'rgba(0,0,0,0.5)'} : '']}>
Ahsan Ali
  • 4,951
  • 2
  • 17
  • 27
  • 2
    Thank you for your answer, I already tried it. but It doesn't make sense because background of the model is a parent component. – Asbar Ali Jan 02 '18 at 10:43
  • Where have you added this condition? You need to add this to your main parent `View` component. Not Modal's `View` – Ahsan Ali Jan 02 '18 at 11:00
  • 1
    Yeah I added to the main view.But nothing changed. 'Test screen' text is on the parent component. not in this current component. it will work if those texts are in the current component – Asbar Ali Jan 02 '18 at 11:09
  • this is the correct answer since animation doesn't work in the same order as the foreground – evanjmg May 11 '21 at 15:35
10

I created a container style then I applied the rgba values for backgroundColor e.g:

modalContainer:{
    flex: 1,
    //backgroundColor: 'transparent',
    backgroundColor: 'rgba(0,0,0,0.7)',
    alignItems: 'center',
    justifyContent: 'center',
},

Then inside the modal I created my actual modal dialog with rounded corners (I achieved this by adding another element inside the modal content and gave it a white background with rounded corners).

cchapman
  • 3,269
  • 10
  • 50
  • 68
Trevor
  • 1,561
  • 1
  • 20
  • 28
10

I managed to get a transparent dark background wich close the modal when you click on it.
I use a first external container in the modal element, which has full screen dimensions. In it, the inner container has a box size and is centered in the screen.

Here the code (react: v16.13, react-native: v0.63.2)

import React from 'react';
import {Modal, Text, TouchableWithoutFeedback, View} from 'react-native';
import {style} from './style';

const MyModal = ({visible, onDismiss}) => {
  return (
    <Modal visible={visible} transparent>
      <TouchableWithoutFeedback onPress={() => onDismiss()}>
        <View style={style.modal}>
          <TouchableWithoutFeedback>
            <View style={style.modalInner}>
              <Text>Something in the modal</Text>
            </View>
          </TouchableWithoutFeedback>
        </View>
      </TouchableWithoutFeedback>
    </Modal>
  );
};

export default MyModal;

The onDismiss is a callback toggling the value of the visible variable given to this component from his parent.

TouchableWithoutFeedback adds the onPress event handling on the containers. The external one respond on click, to close/dismiss the modal. The inner one do nothing (default behavior when onPress is not given).

With the style :

import {StyleSheet} from 'react-native';

export const style = StyleSheet.create({
  modal: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'rgba(0,0,0,0.5)',
  },

  modalInner: {
    height: 200,
    padding: 35,
    justifyContent: 'space-around',
    alignItems: 'center',
    backgroundColor: '#FFF',
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    elevation: 5,
  },
});

Note that the parent element of my <MyModal> is the root <View> of my app, with the style {flex: 1}.

v.nivuahc
  • 809
  • 8
  • 8
9

With react-native-modal, you can use backdropOpacity property to dim background when modal is visible

import React, {useState} from 'react';
import {Button, Text, View} from 'react-native';
import Modal from 'react-native-modal';

function ModalTester() {
  const [isModalVisible, setModalVisible] = useState(false);

  const toggleModal = () => {
    setModalVisible(!isModalVisible);
  };

  render() {
return (
  <View style={{flex: 1}}>
    <Button title="Show modal" onPress={toggleModal} />

    <Modal isVisible={isModalVisible} backdropOpacity={0.3}>
      <View style={{flex: 1}}>
        <Text>Hello!</Text>

        <Button title="Hide modal" onPress={toggleModal} />
      </View>
    </Modal>
  </View>
);
  }
}

export default ModalTester;
MaybeNextTime
  • 561
  • 5
  • 11
6

I just Wrap the whole modalView in another View and simply apply background to it

<View style={styles.modalbackdrop}>   
   <View style={styles.modalView}></View>
</View>

and apply following

backgroundColor: 'rgba(0, 0, 0, 0.8)',
height: '100%',
Shadab Ali
  • 369
  • 3
  • 10
0

This worked for me:

<View style={{opacity: modalVisible? 0.5 : undefined}}>
    <Modal
        animationType="slide"
        transparent={true}
        visible={modalVisible}
        onRequestClose={() => {
           setModalVisible(!modalVisible);
        }}>
        ...
    </Modal>
</View>
hanuruh
  • 220
  • 3
  • 12
-1

You must add statusBarTranslucent props to Modal component and set it to true. Then you will get your desired output. No need to set transparent props to true or any other tedious styles.

Anil Rai
  • 104
  • 2
  • According to react native docs that prop only changes if the modal should go under the status bar, the question is about the background. – p-syche Jan 25 '21 at 12:17
-1

React native provides a prop you can apply to the component

activeOpacity={0.9}

Which you can set to whatever you'd like

prog
  • 173
  • 1
  • 3
  • 12