React-native: [IOS]Keyboard cannot dismiss when two TextInput switch focus in a ScrollView.

Created on 30 Oct 2015  路  11Comments  路  Source: facebook/react-native

There are two TextInput in a ScrollView. When I touch one of them, the keyboard pop-up, then I touch the blank space in ScrollView, the keyboard dismissed. However, if I touch one TextInput, then touch the other, and then touch the blank space in ScrollView again, the keyboard can not dismiss.

Locked

Most helpful comment

I found a way to fixed that, but need to modify the source.
Add the sentence TextInputState.focusTextInput(React.findNodeHandle(this.refs.input)) in the _onFocus function of 'TextInput.js', as followed:

_onFocus: function(event: Event) {
    TextInputState.focusTextInput(React.findNodeHandle(this.refs.input));

    if (this.props.onFocus) {
      this.props.onFocus(event);
    }
  },

All 11 comments

I found the ScrollView's scrollResponderHandleStartShouldSetResponderCapture return true when the focus changed from one TextInput to the other. Because of that, the scrollview will capture the responder event, and consequently the other TextInput's focus cannot be called in js level. But actually, it already become the first responder in native, and the keyboard show. However, there is no focus record in js code, the keyboard cannot be dismissed.

scrollResponderHandleStartShouldSetResponderCapture: function(e: Event): boolean {
    // First see if we want to eat taps while the keyboard is up
    var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
    if (!this.props.keyboardShouldPersistTaps &&
      currentlyFocusedTextInput != null &&
      e.target !== currentlyFocusedTextInput) {
      return true;
    }
    return this.scrollResponderIsAnimating();
  },

yes, we have the same problem. Android have not the problem.

I found a way to fixed that, but need to modify the source.
Add the sentence TextInputState.focusTextInput(React.findNodeHandle(this.refs.input)) in the _onFocus function of 'TextInput.js', as followed:

_onFocus: function(event: Event) {
    TextInputState.focusTextInput(React.findNodeHandle(this.refs.input));

    if (this.props.onFocus) {
      this.props.onFocus(event);
    }
  },

this.refs.input.focus()

you can try my solution.

export default FormContainer = React.createClass({
  mixins: [PureRenderMixin],


  render() {
    return (
      <ScrollView
        showsVerticalScrollIndicator={true}
        automaticallyAdjustContentInsets={false}
        contentContainerStyle={styles.content}
        keyboardDismissMode='on-drag'
        keyboardShouldPersistTaps={true}>
        <View
          onStartShouldSetResponderCapture={(e) => {
            const focusField = TextInputState.currentlyFocusedField();

            if (focusField != null && e.nativeEvent.target != focusField){
              dismissKeyboard();
            }
          }}>
          {this.props.children}
        </View>
      </ScrollView>
    );
  }
});

use onStartShouldSetResponderCapture to intercept interaction change

Two things:

  1. import dismissKeyboard from 'react-native/Libraries/Utilities/dismissKeyboard'; for anyone that is wondering where that comes from
  2. In @hufeng's solution, when transitioning between Input 1 and Input 2, the keyboard toggles (aka hides and then immediately shows again). This UX is less than ideal but I cannot for the life of me figure out how to prevent that from occurring :frowning:

Did anyone submit a PR ? @lvbingru solution worked for me.

when transitioning between Input 1 and Input 2, the keyboard toggles

the @hufeng 's solution can be extended to check if new target is TextInput as well to solve this problem. However till now I haven't find out the way how to check if target (defined by handle) is input or not. Currently I need to enumerate all inputs and get their handle via React.findNodeHandle.

Have someone any idea - either how to obtain all child TextInputs automatically or even better to find out what component instance belong to node handle?

Has anyone got a solution for this? I need 2 taps to get a button press if the focus is on a text input in a scroll view.

Doesn't happen on android.

Hi there! This issue is being closed because it has been inactive for a while.

But don't worry, it will live on with ProductPains! Check out its new home: https://productpains.com/post/react-native/ioskeyboard-cannot-dismiss-when-two-textinput-switch-focus-in-a-scrollview

Product Pains has been very useful in highlighting the top bugs and feature requests:
https://productpains.com/product/react-native?tab=top

Also, if this issue is a bug, please consider sending a pull request with a fix.

@lvbingru solution worked for me with a minor change.

TextInputState.focusTextInput(ReactNative.findNodeHandle(this._inputRef))

Copy paste the above code in _onFocus function within TextInput.js file.

Was this page helpful?
0 / 5 - 0 ratings