From 372d001a5d5e24b68d194e01c356d973642fac86 Mon Sep 17 00:00:00 2001 From: Andrei Coman Date: Tue, 6 Sep 2016 09:45:25 -0700 Subject: [PATCH] Smart textinput scroll Summary: This diff changes the textinput component to only scroll (and interrupt parent views from scrolling), when it is possible for the text inside the component to be scrolled. Before (D3735237), we would intercept all touch events on the textinput if it's focused. But this makes it: a.) impossible to scroll a scrollview from within a textinput that cannot be scrolled; b.) different from iOS behavior. What the component now does is intercept move touches, and check if it can scroll in any direction. If it does, it will intercept the touches and stop the parent component from scrolling; otherwise, it will give the control back to the parent component. Note: this might change in the future to also detect the direction of the scroll, and only block the scroll if the component can scroll in that direction. This is however not trivial, since the scroll needs to be above some threshold of pixels. Blocking the parent view from scrolling until that threshold is passed might cause incorrect behavior in the parent component. Reviewed By: astreet Differential Revision: D3764267 fbshipit-source-id: 47e7b5e03855b3c85789e04fc31a8317afbafa84 --- .../react/views/textinput/ReactEditText.java | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) 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 e548b66ea..ffa6e911a 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 @@ -15,8 +15,8 @@ import java.util.ArrayList; import android.content.Context; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.graphics.Typeface; +import android.graphics.drawable.Drawable; import android.text.Editable; import android.text.InputType; import android.text.SpannableStringBuilder; @@ -29,6 +29,7 @@ import android.text.style.BackgroundColorSpan; import android.text.style.ForegroundColorSpan; import android.view.Gravity; import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; @@ -68,12 +69,12 @@ public class ReactEditText extends EditText { private @Nullable ArrayList mListeners; private @Nullable TextWatcherDelegator mTextWatcherDelegator; private int mStagedInputType; - private boolean mTextIsSelectable = true; private boolean mContainsImages; private boolean mBlurOnSubmit; private @Nullable SelectionWatcher mSelectionWatcher; private @Nullable ContentSizeWatcher mContentSizeWatcher; private final InternalKeyListener mKeyListener; + private boolean mDetectScrollMovement = false; private static final KeyListener sKeyListener = QwertyKeyListener.getInstanceForFullKeyboard(); @@ -124,6 +125,31 @@ public class ReactEditText extends EditText { } } + @Override + public boolean onTouchEvent(MotionEvent ev) { + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + 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); + } + mDetectScrollMovement = false; + } + break; + } + return super.onTouchEvent(ev); + } + // Consume 'Enter' key events: TextView tries to give focus to the next TextInput, but it can't // since we only allow JS to change focus, which in turn causes TextView to crash. @Override @@ -252,12 +278,6 @@ public class ReactEditText extends EditText { setKeyListener(mKeyListener); } - @Override - public void setTextIsSelectable(boolean selectable) { - mTextIsSelectable = selectable; - super.setTextIsSelectable(selectable); - } - // VisibleForTesting from {@link TextInputEventsTestCase}. public void requestFocusFromJS() { mIsJSSettingFocus = true;