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.
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:
import dismissKeyboard from 'react-native/Libraries/Utilities/dismissKeyboard'; for anyone that is wondering where that comes fromDid 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.
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_onFocusfunction of 'TextInput.js', as followed: