Mike K
Mike K

Reputation: 6491

How to avoid having to click TouchableOpacity twice to trigger onPress event?

I'm using this module and the issue is that the Dialogue element that pops up, which is a Modal, has two TouchableOpacity buttons. After typing, when the keyboard is up, clicking the 'submit' TouchableOpacity will first clear/hide the keyboard, and only the second tap on the 'submit' TouchableOpacity will trigger the onPress event. What can I do as a workaround here? I've tried changing it to a Button from react-native and from react-native-elements but it behaves the same way.


Edit:

The component:

    return (
      <Modal
        animationType="fade"
        transparent={true}
        visible={this.props.isDialogVisible}
        onRequestClose={() => {
          this.props.closeDialog();
          this.setState({ inputModal: "" });
        }}
      >
        <View style={[styles.container, { ...modalStyleProps }]}>
          <TouchableOpacity
            style={styles.container}
            activeOpacity={1}
            onPress={() => {
              this.props.closeDialog();
              this.setState({ inputModal: "", openning: true });
            }}
          >
            <View style={[styles.modal_container, { ...dialogStyleProps }]}>
              <View style={styles.modal_body}>
                <Text style={styles.title_modal}>{title}</Text>
                <Text
                  style={[
                    this.props.message ? styles.message_modal : { height: 0 }
                  ]}
                >
                  {this.props.message}
                </Text>
                <TextInput
                  style={styles.input_container}
                  autoCorrect={
                    textProps && textProps.autoCorrect == false ? false : true
                  }
                  autoCapitalize={
                    textProps && textProps.autoCapitalize
                      ? textProps.autoCapitalize
                      : "none"
                  }
                  clearButtonMode={
                    textProps && textProps.clearButtonMode
                      ? textProps.clearButtonMode
                      : "never"
                  }
                  clearTextOnFocus={
                    textProps && textProps.clearTextOnFocus == true
                      ? textProps.clearTextOnFocus
                      : false
                  }
                  keyboardType={
                    textProps && textProps.keyboardType
                      ? textProps.keyboardType
                      : "default"
                  }
                  autoFocus={true}
                  onKeyPress={() => this.setState({ openning: false })}
                  underlineColorAndroid="transparent"
                  placeholder={hintInput}
                  onChangeText={inputModal => {
                    if (this.props.setBackupCommentText) {
                      this.props.setBackupCommentText(inputModal);
                    }

                    this.setState({ inputModal });
                  }}
                  value={value || this.props.backupCommentText}
                  multiline={true}
                />
              </View>
              <View style={styles.btn_container}>
                <TouchableOpacity
                  style={styles.touch_modal}
                  onPress={() => {
                    this.props.closeDialog();
                    this.setState({ inputModal: "", openning: true });
                  }}
                >
                  <Text style={styles.btn_modal_left}>{cancelText}</Text>
                </TouchableOpacity>
                <View style={styles.divider_btn}></View>
                <TouchableOpacity
                  style={styles.touch_modal}
                  onPress={() => {
                    if (
                      this.props.initValueTextInput &&
                      this.props.initValueTextInput.trim().length === 0
                    ) {
                      Toast.show("Comment cannot be empty");
                    } else {
                      this.props.submitInput(value);

                      this.setState({ inputModal: "", openning: true });

                      if (this.props.setBackupCommentText) {
                        this.props.setBackupCommentText("");
                      }
                    }
                  }}
                >
                  <Text style={styles.btn_modal_right}>{submitText}</Text>
                </TouchableOpacity>
              </View>
            </View>
          </TouchableOpacity>
        </View>
      </Modal>
    );

Upvotes: 14

Views: 8821

Answers (4)

Namae Conde
Namae Conde

Reputation: 1

Add keyboardShouldPersistTaps to parent or nearest FlatList or ScrollView,

Determines when the keyboard should stay visible after a tap.

  • 'never' tapping outside of the focused text input when the keyboard is up dismisses the keyboard. When this happens, children won't receive the tap.
  • 'always', the keyboard will not dismiss automatically, and the scroll view will not catch taps, but children of the scroll view can catch taps.
  • 'handled', the keyboard will not dismiss automatically when the tap was handled by children of the scroll view (or captured by an ancestor).
  • false, deprecated, use 'never' instead
  • true, deprecated, use 'always' instead

reference: https://reactnative.dev/docs/scrollview#keyboardshouldpersisttaps

Upvotes: 0

Oleksii Vakhrushev
Oleksii Vakhrushev

Reputation: 29

Just wrap your code inside from react-native-keyboard-aware-scroll-view library

<Modal>
  <KeyboardAwareScrollView>
    ...
  </KeyboardAwareScrollView>
</Modal>

and that's it.

Upvotes: -1

Rajesh N
Rajesh N

Reputation: 6683

For FlatList or ScrollView, you can use following props

keyboardShouldPersistTaps={true}

Upvotes: 2

Mike M
Mike M

Reputation: 4436

This is likely because a parent scrollview is intercepting the tap gesture. To solve this problem, find the nearest ScrollView or FlatList parent and add the keyboardShouldPersistTaps='handled' attribute. This will prevent the keyboard from auto dismissing on the tap (which consumes the tap). You may need to add Keyboard.dismiss() to get it to work as expected.

<ScrollView keyboardShouldPersistTaps='handled'>

...

</ScrollView>

Upvotes: 36

Related Questions