Close react native modal by clicking on overlay?

2020-02-19 01:03发布

Is it possible to close react native modal by clicking on overlay when transparent option is true? Documentation doesn't provide anything about it. Is it possible?

7条回答
Luminary・发光体
2楼-- · 2020-02-19 01:37
        <Modal
            animationType="slide"
            closeOnClick={true}
            transparent={true}
            visible={this.state.modalVisible}
            >
            <TouchableOpacity onPress={() => { this.setModalVisible(!this.state.modalVisible)}} style={{flex:1, justifyContent:'center', alignItems:'center',}}>
                <View style={{flex:0.2,backgroundColor:'white', margin:20, borderRadius:20, borderWidth:2, borderColor:'gray'}}>
                    <Text style={{margin:20}}>모달 테스트</Text>
                </View>
            </TouchableOpacity>
        </Modal>

this code is my solution.

查看更多
爷、活的狠高调
3楼-- · 2020-02-19 01:38

If I understood correctly, you want to close the modal when the user clicks outside of it, right ?

If yes, I searched for this some time ago and the only solution that I remember was this one (which is the one that I've been using so far):

render() { 
  if (!this.state.modalVisible)
    return null
  return (
     <View>
        <Modal 
          animationType="fade"
          transparent={true}
          visible={this.state.modalVisible}
          onRequestClose={() => {this.setModalVisible(false)}}
        >
          <TouchableOpacity 
            style={styles.container} 
            activeOpacity={1} 
            onPressOut={() => {this.setModalVisible(false)}}
          >
            <ScrollView 
              directionalLockEnabled={true} 
              contentContainerStyle={styles.scrollModal}
            >
              <TouchableWithoutFeedback>
                <View style={styles.modalContainer}>
                  // Here you put the content of your modal.
                </View>
              </TouchableWithoutFeedback>
            </ScrollView>
          </TouchableOpacity>   
        </Modal> 
     </View>
  )
} 

// Then on setModalVisible(), you do everything that you need to do when closing or opening the modal.
setModalVisible(visible) {
    this.setState({
        modalVisible: visible,
    })
}

Explanation

This is basically using a TouchableOpacity in the whole screen to get when the user clicks to close the modal. The TouchableWithoutFeedback is to avoid the TouchableOpacity to work inside of the Modal.

If you have a better solution, please share here.

查看更多
来,给爷笑一个
4楼-- · 2020-02-19 01:48

Here is my simple implementation:

<TouchableWithoutFeedback onPress={}> // Code to close your modal goes here
    <View style={styles.background}> // The view to drawn the background
            <View
                onStartShouldSetResponder={() => true}
                style={styles.container}
            > // The view to drawn your modal
            // Your content
            </View>
        </Androw>
    </View>
</TouchableWithoutFeedback>

I use TouchableWithoutFeedback since i do not want to change the background color when clicking on it. I also added onStartShouldSetResponder on the modal view to prevent closing the modal when you click inside the view.

I am also not using the Modal component because i done it using react-navigation.

查看更多
霸刀☆藐视天下
5楼-- · 2020-02-19 01:55
<Modal isVisible={this.state.isVisible}
onBackdropPress={() => this.setState({ isVisible: false })}>
<View style={{ flex: 1 }}>
<Text>I am the modal content!</Text>
</View>
</Modal>
查看更多
Lonely孤独者°
6楼-- · 2020-02-19 01:56

Another solution:

// Modal.js
import React from 'react';
import {
  TouchableWithoutFeedback,
  StyleSheet,
  Modal,
  View,
} from 'react-native';
import t from 'prop-types';


class MyModal extends React.Component {
  static propTypes = {
    children: t.node.isRequired,
    visible: t.bool.isRequired,
    dismiss: t.func.isRequired,
    transparent: t.bool,
    animationType: t.string,
  };

  static defaultProps = {
    animationType: 'none',
    transparent: true,
  };

  render() {
    const { props } = this;
    return (
      <View>
        <Modal
          visible={props.visible}
          transparent={props.transparent}
          onRequestClose={props.dismiss}
          animationType={props.animationType}
        >
        <TouchableWithoutFeedback onPress={props.dismiss}>
          <View style={styles.modalOverlay} />
        </TouchableWithoutFeedback>

        <View style={styles.modalContent}>
          {props.children}
        </View>
        </Modal>
      </View>
    );
  }
}


const styles = StyleSheet.create({
  modalContent: {
    flex: 1,
    justifyContent: 'center',
    margin: '5%',
  },
  modalOverlay: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    backgroundColor: 'rgba(0,0,0,0.5)'
  },
});


export default MyModal;

Usage example:

// SomeScreen.js
import React from 'react';
import { View, Text, Button } from 'react-native';

import Modal from './Modal';


class SomeScreen extends React.Component {
  state = {
    isModalVisible: false,
  };

  showModal = () => this.setState({ isModalVisible: true });
  hideModal = () => this.setState({ isModalVisible: false });

  render() {
    return (
      <View>
        <Button onPress={this.showModal} />
        <Modal
          visible={this.state.isModalVisible}
          dismiss={this.hideModal}
        >
          <Text>Hello, I am modal</Text>
        </Modal>
      </View>
    );
  }
}
查看更多
做自己的国王
7楼-- · 2020-02-19 01:57

We can work it out by adding:

import { TouchableOpacity } from 'react-native';
    <TouchableOpacity onPress={()=>this.setState({modalVisibilty:false})}>
    <View style={{opacity:0, flex:1 }}/>
    </TouchableOpacity>

under the window and another one above and change the layout style to fit your screen.

Explanation:

You will make 2 big hidden buttons to catch the user touch and change the modal visibility state to false.

查看更多
登录 后发表回答