通过单击叠加关闭反应本机模式?

inf*_*-vv 21 javascript react-native

是否有可能通过在选项选项时点击叠加来关闭反应原生模态?文档没有提供任何相关信息.可能吗?transparenttrue

Gui*_*zog 57

如果我理解正确,你想在用户点击它时关闭模态,对吧?

如果是的话,我前段时间搜索过这个问题,我记得的唯一解决方案就是这个(这是我到目前为止使用的那个):

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,
    })
}
Run Code Online (Sandbox Code Playgroud)

说明

这基本上是在整个屏幕中使用TouchableOpacity,以便在用户单击以关闭模式时获取.TouchableWithoutFeedback是为了避免TouchableOpacity在Modal中工作.

如果您有更好的解决方案,请在此处分享.

  • 这个的CSS在哪里? (3认同)
  • 我用这个想法解决了我的问题,虽然我看到 ```TouchableOpacity``` 没有 ```onPressOut```,我不得不使用 ```TouchableOpacity``` 和空动作而不是 `` `TouchableWithoutFeedback``` (2认同)
  • 为了使其工作,“flex: 1”不得包含在“styles.scrollModal”中,但必须包含在“styles.container”中 (2认同)

Tom*_*asB 12

调用的TouchableWithoutFeedback本机组件Pressable允许您检查单击的内容,而不是使用 ,因此允许您仅在单击它而不是其子组件时关闭。

return (
   <View>
      <Modal 
        animationType="slide"
        transparent={true}
        visible={visible}
        onRequestClose={() => {
           setVisible(false)}}
      >
        <Pressable
          onPress={(event) => event.target == event.currentTarget && setVisible(false)}
          style={styles.background}
        >
          <View style={styles.modal}>
             //Content of the modal
          </View>
        </Pressable>   
      </Modal> 
   </View>
)
Run Code Online (Sandbox Code Playgroud)

在这里找到了答案。


Sim*_*ion 8

我们可以通过添加以下内容来解决:

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

窗口下方和上方另一个窗口,然后更改布局样式以适合您的屏幕。

解释:

您将制作 2 个大的隐藏按钮来捕获用户触摸并将模式可见性状态更改为 false。


Mic*_*ace 8

这是我的简单实现:

<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>
Run Code Online (Sandbox Code Playgroud)

我使用 TouchableWithoutFeedback 因为我不想在单击它时更改背景颜色。我还在模态视图上添加了 onStartShouldSetResponder,以防止在视图内部单击时关闭模态。

我也没有使用模态组件,因为我使用反应导航来完成它。


sor*_*rat 7

另一个解决方案:

// 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;
Run Code Online (Sandbox Code Playgroud)

用法示例:

// 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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

简单的解决方案。您需要一个 touchableOpacity 用于单击外部,另一个 touchableOpacity 用于实际模态,它不会对 onPress 执行任何操作。

import React, { Component } from 'react'
import { View, StyleSheet, TouchableOpacity, Modal} from 'react-native';

export class Modal extends Component {
    constructor(props){
        this.state = { modalVisible : true}
    }
    render() {
        return (
            <View>
                <Modal
                    animationType="slide"
                    transparent={true}
                    visible={this.state.modalVisible}
                    onRequestClose={() => { this.setState({modalVisible: false})
                    }}
                  >
                    <TouchableOpacity style={styles.modalContainer} onPress={() => { this.setState({ modalVisible : false})}}>
                        <TouchableOpacity style={styles.modal} onPress={() => console.log('do nothing')} activeOpacity={1} >
                            Modal Content...
                        </TouchableOpacity>
                    </TouchableOpacity>
                </Modal>
            </View>
        )
    }
}


const styles = StyleSheet.create({
    modalContainer: {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
    },
    modal: {
      width: 155,
      height: 300
    },
});

export default Modal;
Run Code Online (Sandbox Code Playgroud)

activeOpacity={1} 只是移除 touchableOpacity 淡入淡出效果


小智 6

<Modal isVisible={this.state.isVisible}
onBackdropPress={() => this.setState({ isVisible: false })}>
<View style={{ flex: 1 }}>
<Text>I am the modal content!</Text>
</View>
</Modal>
Run Code Online (Sandbox Code Playgroud)

  • `onBackdropPress` 不是反应原生 `Modal` 组件的有效 prop。不过会很好! (8认同)

Pra*_*rle 5

使用 React-native 的 TouchableWithoutFeedback 和 Modal:

<Modal
  visible={visible}//modal visible true or false
  onRequestClose={()=>onClose(false)} // function to close modal
  transparent={true}
>
 <TouchableWithoutFeedback
   onPress={()=>onClose(false)}//outer button/view
   <View style={{flex:1, backgroundColor:'rgba(0,0,0,0.5)'}}>//for transparent view, this is outer view
    <TouchableWithoutFeedback>// outer button so any child view can be added
      <View>// this inner view
       <View>
       //your content goes here
       </View>
      </View>
    </TouchableWithoutFeedback>
   </View>
 </TouchableWithoutFeedback>
</Modal>
Run Code Online (Sandbox Code Playgroud)

如果您想更好地添加平面列表以提供高度,这样内容就不会消失