Clean up some grossness in ScrollResponder
Summary: Still gross but less gross. Reviewed By: sebmarkbage Differential Revision: D7107180 fbshipit-source-id: 31f1639a8f44e4ab247c338001a4a5c9b4b83cdf
This commit is contained in:
parent
8102e35271
commit
a275eac56e
|
@ -23,7 +23,6 @@ const performanceNow = require('fbjs/lib/performanceNow');
|
|||
const warning = require('fbjs/lib/warning');
|
||||
|
||||
const { ScrollViewManager } = require('NativeModules');
|
||||
const { getInstanceFromNode } = require('ReactNativeComponentTree');
|
||||
|
||||
/**
|
||||
* Mixin that can be integrated in order to handle scrolling that plays well
|
||||
|
@ -114,15 +113,6 @@ type State = {
|
|||
};
|
||||
type Event = Object;
|
||||
|
||||
function isTagInstanceOfTextInput(tag) {
|
||||
const instance = getInstanceFromNode(tag);
|
||||
return instance && instance.viewConfig && (
|
||||
instance.viewConfig.uiViewClassName === 'AndroidTextInput' ||
|
||||
instance.viewConfig.uiViewClassName === 'RCTMultilineTextInputView' ||
|
||||
instance.viewConfig.uiViewClassName === 'RCTSinglelineTextInputView'
|
||||
);
|
||||
}
|
||||
|
||||
const ScrollResponderMixin = {
|
||||
mixins: [Subscribable.Mixin],
|
||||
scrollResponderMixinGetInitialState: function(): State {
|
||||
|
@ -196,17 +186,27 @@ const ScrollResponderMixin = {
|
|||
* Invoke this from an `onStartShouldSetResponderCapture` event.
|
||||
*/
|
||||
scrollResponderHandleStartShouldSetResponderCapture: function(e: Event): boolean {
|
||||
// First see if we want to eat taps while the keyboard is up
|
||||
// The scroll view should receive taps instead of its descendants if:
|
||||
// * it is already animating/decelerating
|
||||
if (this.scrollResponderIsAnimating()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// * the keyboard is up, keyboardShouldPersistTaps is 'never' (the default),
|
||||
// and a new touch starts with a non-textinput target (in which case the
|
||||
// first tap should be sent to the scroll view and dismiss the keyboard,
|
||||
// then the second tap goes to the actual interior view)
|
||||
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||
const {keyboardShouldPersistTaps} = this.props;
|
||||
const keyboardNeverPersistTaps = !keyboardShouldPersistTaps ||
|
||||
keyboardShouldPersistTaps === 'never';
|
||||
if (keyboardNeverPersistTaps &&
|
||||
currentlyFocusedTextInput != null &&
|
||||
!isTagInstanceOfTextInput(e.target)) {
|
||||
currentlyFocusedTextInput != null
|
||||
/* && !TextInputState.isTextInput(e.target) */) {
|
||||
return true;
|
||||
}
|
||||
return this.scrollResponderIsAnimating();
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -192,10 +192,6 @@ const DataDetectorTypes = [
|
|||
|
||||
const TextInput = createReactClass({
|
||||
displayName: 'TextInput',
|
||||
statics: {
|
||||
/* TODO(brentvatne) docs are needed for this */
|
||||
State: TextInputState,
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
...ViewPropTypes,
|
||||
|
@ -667,24 +663,30 @@ const TextInput = createReactClass({
|
|||
|
||||
componentDidMount: function() {
|
||||
this._lastNativeText = this.props.value;
|
||||
if (!this.context.focusEmitter) {
|
||||
const tag = ReactNative.findNodeHandle(this._inputRef);
|
||||
if (tag != null) {
|
||||
// tag is null only in unit tests
|
||||
TextInputState.registerInput(tag);
|
||||
}
|
||||
|
||||
if (this.context.focusEmitter) {
|
||||
this._focusSubscription = this.context.focusEmitter.addListener(
|
||||
'focus',
|
||||
el => {
|
||||
if (this === el) {
|
||||
this.requestAnimationFrame(this.focus);
|
||||
} else if (this.isFocused()) {
|
||||
this.blur();
|
||||
}
|
||||
},
|
||||
);
|
||||
if (this.props.autoFocus) {
|
||||
this.context.onFocusRequested(this);
|
||||
}
|
||||
} else {
|
||||
if (this.props.autoFocus) {
|
||||
this.requestAnimationFrame(this.focus);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this._focusSubscription = this.context.focusEmitter.addListener(
|
||||
'focus',
|
||||
el => {
|
||||
if (this === el) {
|
||||
this.requestAnimationFrame(this.focus);
|
||||
} else if (this.isFocused()) {
|
||||
this.blur();
|
||||
}
|
||||
},
|
||||
);
|
||||
if (this.props.autoFocus) {
|
||||
this.context.onFocusRequested(this);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -693,6 +695,10 @@ const TextInput = createReactClass({
|
|||
if (this.isFocused()) {
|
||||
this.blur();
|
||||
}
|
||||
const tag = ReactNative.findNodeHandle(this._inputRef);
|
||||
if (tag != null) {
|
||||
TextInputState.unregisterInput(tag);
|
||||
}
|
||||
},
|
||||
|
||||
getChildContext(): ViewChildContext {
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
const Platform = require('Platform');
|
||||
const UIManager = require('UIManager');
|
||||
|
||||
const inputs = new Set();
|
||||
|
||||
const TextInputState = {
|
||||
/**
|
||||
* Internal state
|
||||
|
@ -68,7 +70,19 @@ const TextInputState = {
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
registerInput: function(textFieldID: number) {
|
||||
inputs.add(textFieldID);
|
||||
},
|
||||
|
||||
unregisterInput: function(textFieldID: number) {
|
||||
inputs.delete(textFieldID);
|
||||
},
|
||||
|
||||
isTextInput: function(textFieldID: number) {
|
||||
return inputs.has(textFieldID);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = TextInputState;
|
||||
|
|
Loading…
Reference in New Issue