Don't dismiss keyboard when tapping another text input

Summary:
When using text inputs inside a ScrollView with `keyboardShouldPersistTaps=false` (default behavior) tapping another text input dismisses the keyboard instead of keeping it open and focusing the new text input which I think is the better and expected behavior.

See #10628 for more discussion about that. Note that this affects nothing but the behavior with text inputs unlike #10628.

cc satya164 MaxLap ericvicenti
Closes https://github.com/facebook/react-native/pull/10887

Differential Revision: D4178474

Pulled By: ericvicenti

fbshipit-source-id: 0c62ea2fac0017d559d1f8674b0a686a5e1b3d2d
This commit is contained in:
Janic Duplessis 2016-11-25 05:30:05 -08:00 committed by Facebook Github Bot
parent 0e55f5b26d
commit 552c601921
3 changed files with 27 additions and 5 deletions

View File

@ -19,6 +19,7 @@ var Subscribable = require('Subscribable');
var TextInputState = require('TextInputState');
var UIManager = require('UIManager');
var { getInstanceFromNode } = require('ReactNativeComponentTree');
var { ScrollViewManager } = require('NativeModules');
var invariant = require('fbjs/lib/invariant');
@ -112,6 +113,15 @@ type State = {
};
type Event = Object;
function isTagInstanceOfTextInput(tag) {
var instance = getInstanceFromNode(tag);
return instance && instance.viewConfig && (
instance.viewConfig.uiViewClassName === 'AndroidTextInput' ||
instance.viewConfig.uiViewClassName === 'RCTTextView' ||
instance.viewConfig.uiViewClassName === 'RCTTextField'
);
}
var ScrollResponderMixin = {
mixins: [Subscribable.Mixin],
scrollResponderMixinGetInitialState: function(): State {
@ -172,7 +182,7 @@ var ScrollResponderMixin = {
* that *doesn't* give priority to nested views (hence the capture phase):
*
* - Currently animating.
* - Tapping anywhere that is not the focused input, while the keyboard is
* - Tapping anywhere that is not a text input, while the keyboard is
* up (which should dismiss the keyboard).
*
* Invoke this from an `onStartShouldSetResponderCapture` event.
@ -182,7 +192,7 @@ var ScrollResponderMixin = {
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
if (!this.props.keyboardShouldPersistTaps &&
currentlyFocusedTextInput != null &&
e.target !== currentlyFocusedTextInput) {
!isTagInstanceOfTextInput(e.target)) {
return true;
}
return this.scrollResponderIsAnimating();

View File

@ -101,7 +101,7 @@ function requireNativeComponent(
return createReactNativeComponentClass(viewConfig);
}
var TypeToDifferMap = {
const TypeToDifferMap = {
// iOS Types
CATransform3D: matricesDiffer,
CGPoint: pointsDiffer,
@ -115,7 +115,7 @@ function processColorArray(colors: []): [] {
return colors && colors.map(processColor);
}
var TypeToProcessorMap = {
const TypeToProcessorMap = {
// iOS Types
CGColor: processColor,
CGColorArray: processColorArray,

View File

@ -200,6 +200,18 @@ public class TouchTargetHelper {
float eventCoords[], View view) {
PointerEvents pointerEvents = view instanceof ReactPointerEventsView ?
((ReactPointerEventsView) view).getPointerEvents() : PointerEvents.AUTO;
// Views that are disabled should never be the target of pointer events. However, their children
// can be because some views (SwipeRefreshLayout) use enabled but still have children that can
// be valid targets.
if (!view.isEnabled()) {
if (pointerEvents == PointerEvents.AUTO) {
pointerEvents = PointerEvents.BOX_NONE;
} else if (pointerEvents == PointerEvents.BOX_ONLY) {
pointerEvents = PointerEvents.NONE;
}
}
if (pointerEvents == PointerEvents.NONE) {
// This view and its children can't be the target
return null;
@ -209,7 +221,7 @@ public class TouchTargetHelper {
return view;
} else if (pointerEvents == PointerEvents.BOX_NONE) {
// This view can't be the target, but its children might
// This view can't be the target, but its children might.
if (view instanceof ViewGroup) {
View targetView = findTouchTargetView(eventCoords, (ViewGroup) view);
if (targetView != view) {