Android: Add onScroll event to TextInput

Summary:
Corresponding iOS PR: https://github.com/facebook/react-native/pull/11002

This adds an onScroll event to TextInput which is useful when a multiline TextInput has so much content that it is scrollable.

**Test plan (required)**

Verified the event works properly in a test app. Also, my team uses this event in our app.

Adam Comella
Microsoft Corp.
Closes https://github.com/facebook/react-native/pull/11001

Differential Revision: D4220941

Pulled By: mkonicek

fbshipit-source-id: 7e420579946f2ae840c9e1fcdc8afab68007da17
This commit is contained in:
Adam Comella 2017-02-06 07:22:09 -08:00 committed by Facebook Github Bot
parent eb4be7af38
commit 69e98cfc75
5 changed files with 77 additions and 0 deletions

View File

@ -739,6 +739,7 @@ const TextInput = React.createClass({
children={children}
disableFullscreenUI={this.props.disableFullscreenUI}
textBreakStrategy={this.props.textBreakStrategy}
onScroll={this._onScroll}
/>;
return (

View File

@ -14,6 +14,7 @@ android_library(
react_native_target('java/com/facebook/react/uimanager:uimanager'),
react_native_target('java/com/facebook/react/uimanager/annotations:annotations'),
react_native_target('java/com/facebook/react/views/imagehelper:imagehelper'),
react_native_target('java/com/facebook/react/views/scroll:scroll'),
react_native_target('java/com/facebook/react/views/text:text'),
react_native_target('java/com/facebook/react/views/view:view'),
],

View File

@ -80,6 +80,7 @@ public class ReactEditText extends EditText {
private @Nullable String mReturnKeyType;
private @Nullable SelectionWatcher mSelectionWatcher;
private @Nullable ContentSizeWatcher mContentSizeWatcher;
private @Nullable ScrollWatcher mScrollWatcher;
private final InternalKeyListener mKeyListener;
private boolean mDetectScrollMovement = false;
@ -106,6 +107,7 @@ public class ReactEditText extends EditText {
mTextWatcherDelegator = null;
mStagedInputType = getInputType();
mKeyListener = new InternalKeyListener();
mScrollWatcher = null;
}
// After the text changes inside an EditText, TextView checks if a layout() has been requested.
@ -171,6 +173,15 @@ public class ReactEditText extends EditText {
return super.onKeyUp(keyCode, event);
}
@Override
protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
super.onScrollChanged(horiz, vert, oldHoriz, oldVert);
if (mScrollWatcher != null) {
mScrollWatcher.onScrollChanged(horiz, vert, oldHoriz, oldVert);
}
}
@Override
public void clearFocus() {
setFocusableInTouchMode(false);
@ -220,6 +231,10 @@ public class ReactEditText extends EditText {
mContentSizeWatcher = contentSizeWatcher;
}
public void setScrollWatcher(ScrollWatcher scrollWatcher) {
mScrollWatcher = scrollWatcher;
}
@Override
public void setSelection(int start, int end) {
// Skip setting the selection if the text wasn't set because of an out of date value.

View File

@ -48,6 +48,8 @@ import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
import com.facebook.react.views.scroll.ScrollEvent;
import com.facebook.react.views.scroll.ScrollEventType;
import com.facebook.react.views.text.DefaultStyleValuesUtil;
import com.facebook.react.views.text.ReactFontManager;
import com.facebook.react.views.text.ReactTextUpdate;
@ -278,6 +280,15 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
}
}
@ReactProp(name = "onScroll", defaultBoolean = false)
public void setOnScroll(final ReactEditText view, boolean onScroll) {
if (onScroll) {
view.setScrollWatcher(new ReactScrollWatcher(view));
} else {
view.setScrollWatcher(null);
}
}
@ReactProp(name = "placeholder")
public void setPlaceholder(ReactEditText view, @Nullable String placeholder) {
view.setHint(placeholder);
@ -772,6 +783,41 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
}
}
private class ReactScrollWatcher implements ScrollWatcher {
private ReactEditText mReactEditText;
private EventDispatcher mEventDispatcher;
private int mPreviousHoriz;
private int mPreviousVert;
public ReactScrollWatcher(ReactEditText editText) {
mReactEditText = editText;
ReactContext reactContext = (ReactContext) editText.getContext();
mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
}
@Override
public void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
if (mPreviousHoriz != horiz || mPreviousVert != vert) {
ScrollEvent event = ScrollEvent.obtain(
mReactEditText.getId(),
ScrollEventType.SCROLL,
horiz,
vert,
0, // can't get content width
0, // can't get content height
mReactEditText.getWidth(),
mReactEditText.getHeight()
);
mEventDispatcher.dispatchEvent(event);
mPreviousHoriz = horiz;
mPreviousVert = vert;
}
}
}
@Override
public @Nullable Map getExportedViewConstants() {
return MapBuilder.of(

View File

@ -0,0 +1,14 @@
/**
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.views.textinput;
public interface ScrollWatcher {
public void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert);
}