Skip to content

Commit

Permalink
Smart textinput scroll
Browse files Browse the repository at this point in the history
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
  • Loading branch information
andreicoman11 authored and Facebook Github Bot 0 committed Sep 6, 2016
1 parent 3efe95d commit 372d001
Showing 1 changed file with 28 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

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;
Expand All @@ -29,6 +29,7 @@
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;
Expand Down Expand Up @@ -68,12 +69,12 @@ public class ReactEditText extends EditText {
private @Nullable ArrayList<TextWatcher> 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();

Expand Down Expand Up @@ -124,6 +125,31 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
}
}

@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
Expand Down Expand Up @@ -252,12 +278,6 @@ public void setInputType(int type) {
setKeyListener(mKeyListener);
}

@Override
public void setTextIsSelectable(boolean selectable) {
mTextIsSelectable = selectable;
super.setTextIsSelectable(selectable);
}

// VisibleForTesting from {@link TextInputEventsTestCase}.
public void requestFocusFromJS() {
mIsJSSettingFocus = true;
Expand Down

0 comments on commit 372d001

Please sign in to comment.