diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 8e1e74ab845ac7..7c2e6776911119 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -90,6 +90,10 @@ public class ReactEditText extends AppCompatEditText protected int mNativeEventCount; private static final int UNSET = -1; + private static final int LEFT = -1; + private static final int UP = -1; + private static final int RIGHT = 1; + private static final int DOWN = 1; private @Nullable ArrayList mListeners; private @Nullable TextWatcherDelegator mTextWatcherDelegator; @@ -111,6 +115,8 @@ public class ReactEditText extends AppCompatEditText private int mFontStyle = ReactTypefaceUtils.UNSET; private boolean mAutoFocus = false; private boolean mDidAttachToWindow = false; + private float mPreviousYCoordinates; + private float mPreviousXCoordinates; private ReactViewBackgroundManager mReactBackgroundManager; @@ -202,20 +208,31 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: + mPreviousYCoordinates = ev.getY(); + mPreviousXCoordinates = ev.getX(); mDetectScrollMovement = true; // Disallow parent views to intercept touch events, until we can detect if we should be // capturing these touches or not. this.getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: - if (mDetectScrollMovement) { - if (!canScrollVertically(-1) - && !canScrollVertically(1) - && !canScrollHorizontally(-1) - && !canScrollHorizontally(1)) { - // We cannot scroll, let parent views take care of these touches. - this.getParent().requestDisallowInterceptTouchEvent(false); - } + float horizontalScroll = mPreviousXCoordinates - ev.getX(); + float verticalScroll = mPreviousYCoordinates - ev.getY(); + boolean enableParentScroll = false; + boolean isSwipeVertical = Math.abs(verticalScroll) > Math.abs(horizontalScroll); + if (isSwipeVertical) { + boolean scrollDirectionUp = verticalScroll < 0; + boolean enableParentScrollUp = scrollDirectionUp && !canScrollVertically(UP); + boolean enableParentScrollDown = !scrollDirectionUp && !canScrollVertically(DOWN); + enableParentScroll = enableParentScrollDown || enableParentScrollUp; + } else { + boolean scrollDirectionRight = horizontalScroll > 0; + boolean enableParentScrollRight = scrollDirectionRight && !canScrollHorizontally(RIGHT); + boolean enableParentScrollLeft = !scrollDirectionRight && !canScrollHorizontally(LEFT); + enableParentScroll = enableParentScrollRight || enableParentScrollLeft; + } + if (mDetectScrollMovement && enableParentScroll) { + this.getParent().requestDisallowInterceptTouchEvent(false); mDetectScrollMovement = false; } break; diff --git a/packages/rn-tester/js/examples/ScrollView/ScrollViewTextInputExample.js b/packages/rn-tester/js/examples/ScrollView/ScrollViewTextInputExample.js new file mode 100644 index 00000000000000..433819e8d1f7c0 --- /dev/null +++ b/packages/rn-tester/js/examples/ScrollView/ScrollViewTextInputExample.js @@ -0,0 +1,78 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +'use strict'; + +const React = require('react'); +const {ScrollView, Text, TextInput} = require('react-native'); + +exports.title = 'ScrollView with TextInputs'; +exports.description = 'Displays a list of TextInputs in a ScrollView'; +exports.examples = [ + { + title: 'ScrollView with TextInputs - vertical', + description: + 'Displays a list of scrollable TextInputs in a vertical ScrollView', + render: function(): React.Node { + return ( + + + Normal Text + Normal Text + Normal Text + Normal Text + Normal Text + Normal Text + Normal Text + Normal Text + Normal Text + + ); + }, + }, + { + title: 'ScrollView with TextInputs - horizontal', + description: + 'Displays a list of scrollable TextInputs in a horizontal ScrollView', + render(): React.Element { + return ( + + + Normal Text + Normal Text + Normal Text + Normal Text + + ); + }, + }, +]; diff --git a/packages/rn-tester/js/utils/RNTesterList.android.js b/packages/rn-tester/js/utils/RNTesterList.android.js index ac0a6281b7b864..a9966997a14026 100644 --- a/packages/rn-tester/js/utils/RNTesterList.android.js +++ b/packages/rn-tester/js/utils/RNTesterList.android.js @@ -79,6 +79,11 @@ const ComponentExamples: Array = [ category: 'Basic', module: require('../examples/ScrollView/ScrollViewAnimatedExample'), }, + { + key: 'ScrollViewTextInputExample', + category: 'Basic', + module: require('../examples/ScrollView/ScrollViewTextInputExample'), + }, { key: 'SectionList-onEndReached', module: require('../examples/SectionList/SectionList-onEndReached'),