React Native - как отследить сенсорные события за компонентом абсолютной позиции

Я пытаюсь иметь всплывающее диалоговое окно (созданное как компонент с позицией: "абсолютный") и закрывать его, когда пользователь нажимает за пределами всплывающего окна.

Я новичок в React Native, поэтому другие вещи, которые я сделал, могут быть неправильными, простите меня за это:)

Это скриншот всплывающего окна, когда оно открыто введите описание изображения здесь

Это часть кода:

Из всплывающего компонента:

render() {
    if (!this.props.open) {
      return <View />
    }
    return (
      <View style={styles.container}>
        <View style={styles.popupStyle}>
            <View style={{flex:1, justifyContent: 'center', marginRight: 10}}>
                <View style={styles.amountEnterStyle}>
                  <TextInput
                    keyboardType={'numeric'}
                    underlineColorAndroid='transparent'
                    autoCorrect={false}
                    style={styles.textInputStyle}
                    value={this.state.amount}
                    onChangeText={this._onAmountEnter.bind(this)} />
                  <Text style={styles.currencyTextStyle}>NIS</Text>
                </View>
                <View style={styles.separatorStyle} />
                    <View style={styles.categorySectionStyle}>
                      {this._renderCategoryDropdown()}
                    </View>
              </View>
            <View style={{justifyContent: 'center'}}>
              <TouchableWithoutFeedback
                onPress={this._onAddPaymentClicked.bind(this)} >
                <View style={{width: 110, height:100, backgroundColor: "#ff0000"}} />
              </TouchableWithoutFeedback>
            </View>
        </View>
      </View>
    );

const styles = StyleSheet.create({
    container: {
      position: 'absolute',
      top: 0,
      bottom: 0,
      left: 0,
      right: 0,
      width: undefined,
      height: undefined,
      justifyContent: 'center',
      alignItems: 'center',
    },
    amountEnterStyle: {
      justifyContent: 'center',
      alignItems: 'center',
      flexDirection: 'row'
    },
    textInputStyle: {
      width: 100,
      fontSize: 50,
      fontWeight: 'bold',
      height: 65,
      flex: 1,
      marginTop: -20,
      paddingBottom: 0,
      marginBottom: 0,
      marginLeft:10,
      textAlignVertical: 'center'
    },
    currencyTextStyle: {
      fontSize: 50,
      color: '#c0c0c0',
      marginTop: -20,
      textAlignVertical: 'center'
    },
    separatorStyle: {
      height: 2,
      marginTop: 0,
      backgroundColor: '#c0c0c0',
    },
    categorySectionStyle: {
        justifyContent: 'flex-start',
        flexDirection: 'row',
        alignItems: 'flex-start',
        marginTop: 8
    },
    categoryColorDotStyle: {
      width: 20,
      height: 20,
      borderRadius: 100/2,
      marginLeft: 10,
      marginTop: 5,
    },
    categoryTextStyle: {
      fontSize: 24,
      marginHorizontal: 4,
      color: '#c0c0c0',
      marginLeft: 10,
      paddingRight: 10,
      marginTop: -3
    },
    popupStyle: {
      width: Dimensions.get('window').width - 60,
      flexDirection: 'row',
      justifyContent: 'space-between',
      height: 150,
      paddingRight:10,
      paddingLeft:10,
      borderRadius: 2,
      margin: 20,
      padding: 10,
      opacity: 1,
      borderRadius: 10,
      backgroundColor: '#ffffff'
   },
   dropdownSeparator: {
    height: 1,
    backgroundColor: 'cornflowerblue'
  },

И это компонент хостинга:

render() {
    var totalIncome = this.props.balance.totalIncome;
    var totalExpanses = this.props.balance.totalExpanses;
    return (
      <View style={{flex:1, justifyContent: 'space-between'}}>
        <Image pointerEvents='none' source={require('../../res/background.png')} style={styles.container} />
        <MainScreenHeader onSettingPress={this._onBalanceSettingsPress.bind(this)}/>
        <MainBalanceCounter totalCount={totalIncome} currentCount={totalIncome-totalExpanses} />
        <View style={{justifyContent: 'center', alignItems: 'center', marginBottom: 150}}>
          <AddPaymentButton onPress={this._onAddPaymentPress.bind(this)} />
          <PaymentPopup
              open={this.state.paymentPopupOpen}
              onAddPaymentClicked={this._onPaymentPopupAddClicked.bind(this)} />
        </View>

      </View>
    );
  }


const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    width: undefined,
    height: undefined,
    backgroundColor:'transparent',
    justifyContent: 'center',
    alignItems: 'center',
  },
  innerContainer: {
    justifyContent: 'space-around',
    alignItems: 'center',
    flex: 1,
    backgroundColor: 'transparent'
  },
});

Я пытался сделать что-то, чтобы ловить клики, которые происходят вне всплывающего окна, но безуспешно.

Любая помощь будет высоко ценится,

Спасибо, Гиора.

1 ответ

Решение

Ты пробовал react-native-modalbox? Я использую его в своих приложениях, и он прекрасно работает. Если у вас есть сенсорные события позади модального, он закроется. Кроме того, вы можете определить, какой размер вы хотите сделать модальным. Это не должно занимать весь экран.

В противном случае вы были на правильном пути. Тебе нужен TouchableWithoutFeedback компонент, который покрывает всю ширину и высоту экрана. Ваше всплывающее окно будет рядом с этим компонентом с более высоким индексом zIndex. Дайте мне знать, если вы хотите пойти по этому пути, и я могу дать больше советов. Ура!

Другие вопросы по тегам