mirror of
https://github.com/status-im/react-native.git
synced 2025-01-27 01:40:08 +00:00
Add onSelectionChange for Android TextInput
Summary: public Add an onSelectionChange method to TextInput that works on Android same as iOS Reviewed By: andreicoman11 Differential Revision: D2780131 fb-gh-sync-id: 9b3b8fbd9ea653d43e3107a338e4bc08bde2e8c6
This commit is contained in:
parent
857dd59340
commit
6dc6794881
@ -216,6 +216,10 @@ var TextInput = React.createClass({
|
||||
* Callback that is called when text input ends.
|
||||
*/
|
||||
onEndEditing: PropTypes.func,
|
||||
/**
|
||||
* Callback that is called when the text input selection is changed
|
||||
*/
|
||||
onSelectionChange: PropTypes.func,
|
||||
/**
|
||||
* Callback that is called when the text input's submit button is pressed.
|
||||
* Invalid if multiline={true} is specified.
|
||||
@ -474,6 +478,17 @@ var TextInput = React.createClass({
|
||||
},
|
||||
|
||||
_renderAndroid: function() {
|
||||
var onSelectionChange;
|
||||
if (this.props.selectionState || this.props.onSelectionChange) {
|
||||
onSelectionChange = (event: Event) => {
|
||||
if (this.props.selectionState) {
|
||||
var selection = event.nativeEvent.selection;
|
||||
this.props.selectionState.update(selection.start, selection.end);
|
||||
}
|
||||
this.props.onSelectionChange && this.props.onSelectionChange(event);
|
||||
};
|
||||
}
|
||||
|
||||
var autoCapitalize = UIManager.UIText.AutocapitalizationType[this.props.autoCapitalize];
|
||||
var textAlign =
|
||||
UIManager.AndroidTextInput.Constants.TextAlign[this.props.textAlign];
|
||||
@ -489,6 +504,7 @@ var TextInput = React.createClass({
|
||||
if (childCount > 1) {
|
||||
children = <Text>{children}</Text>;
|
||||
}
|
||||
|
||||
var textContainer =
|
||||
<AndroidTextInput
|
||||
ref="input"
|
||||
@ -505,6 +521,7 @@ var TextInput = React.createClass({
|
||||
onFocus={this._onFocus}
|
||||
onBlur={this._onBlur}
|
||||
onChange={this._onChange}
|
||||
onSelectionChange={onSelectionChange}
|
||||
onTextInput={this._onTextInput}
|
||||
onEndEditing={this.props.onEndEditing}
|
||||
onSubmitEditing={this.props.onSubmitEditing}
|
||||
|
@ -64,6 +64,7 @@ public class ReactEditText extends EditText {
|
||||
private @Nullable TextWatcherDelegator mTextWatcherDelegator;
|
||||
private int mStagedInputType;
|
||||
private boolean mContainsImages;
|
||||
private @Nullable SelectionWatcher mSelectionWatcher;
|
||||
|
||||
public ReactEditText(Context context) {
|
||||
super(context);
|
||||
@ -150,6 +151,27 @@ public class ReactEditText extends EditText {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged(int selStart, int selEnd) {
|
||||
super.onSelectionChanged(selStart, selEnd);
|
||||
if (mSelectionWatcher != null && hasFocus()) {
|
||||
mSelectionWatcher.onSelectionChanged(selStart, selEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFocusChanged(
|
||||
boolean focused, int direction, Rect previouslyFocusedRect) {
|
||||
super.onFocusChanged(focused, direction, previouslyFocusedRect);
|
||||
if (focused && mSelectionWatcher != null) {
|
||||
mSelectionWatcher.onSelectionChanged(getSelectionStart(), getSelectionEnd());
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelectionWatcher(SelectionWatcher selectionWatcher) {
|
||||
mSelectionWatcher = selectionWatcher;
|
||||
}
|
||||
|
||||
/*protected*/ int getStagedInputType() {
|
||||
return mStagedInputType;
|
||||
}
|
||||
@ -170,7 +192,8 @@ public class ReactEditText extends EditText {
|
||||
mStagedInputType = type;
|
||||
}
|
||||
|
||||
/* package */ void requestFocusFromJS() {
|
||||
// VisibleForTesting from {@link TextInputEventsTestCase}.
|
||||
public void requestFocusFromJS() {
|
||||
mIsJSSettingFocus = true;
|
||||
requestFocus();
|
||||
mIsJSSettingFocus = false;
|
||||
|
@ -166,6 +166,15 @@ public class ReactTextInputManager extends
|
||||
(int) Math.ceil(PixelUtil.toPixelFromSP(fontSize)));
|
||||
}
|
||||
|
||||
@ReactProp(name = "onSelectionChange", defaultBoolean = false)
|
||||
public void setOnSelectionChange(final ReactEditText view, boolean onSelectionChange) {
|
||||
if (onSelectionChange) {
|
||||
view.setSelectionWatcher(new ReactSelectionWatcher(view));
|
||||
} else {
|
||||
view.setSelectionWatcher(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "placeholder")
|
||||
public void setPlaceholder(ReactEditText view, @Nullable String placeholder) {
|
||||
view.setHint(placeholder);
|
||||
@ -418,6 +427,40 @@ public class ReactTextInputManager extends
|
||||
});
|
||||
}
|
||||
|
||||
private class ReactSelectionWatcher implements SelectionWatcher {
|
||||
|
||||
private ReactEditText mReactEditText;
|
||||
private EventDispatcher mEventDispatcher;
|
||||
private int mPreviousSelectionStart;
|
||||
private int mPreviousSelectionEnd;
|
||||
|
||||
public ReactSelectionWatcher(ReactEditText editText) {
|
||||
mReactEditText = editText;
|
||||
ReactContext reactContext = (ReactContext) editText.getContext();
|
||||
mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectionChanged(int start, int end) {
|
||||
// Android will call us back for both the SELECTION_START span and SELECTION_END span in text
|
||||
// To prevent double calling back into js we cache the result of the previous call and only
|
||||
// forward it on if we have new values
|
||||
if (mPreviousSelectionStart != start || mPreviousSelectionEnd != end) {
|
||||
mEventDispatcher.dispatchEvent(
|
||||
new ReactTextInputSelectionEvent(
|
||||
mReactEditText.getId(),
|
||||
SystemClock.uptimeMillis(),
|
||||
start,
|
||||
end
|
||||
)
|
||||
);
|
||||
|
||||
mPreviousSelectionStart = start;
|
||||
mPreviousSelectionEnd = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map getExportedViewConstants() {
|
||||
return MapBuilder.of(
|
||||
|
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2015-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;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.events.Event;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
|
||||
/**
|
||||
* Event emitted by EditText native view when the text selection changes.
|
||||
*/
|
||||
/* package */ class ReactTextInputSelectionEvent
|
||||
extends Event<ReactTextInputSelectionEvent> {
|
||||
|
||||
private static final String EVENT_NAME = "topSelectionChange";
|
||||
|
||||
private int mSelectionStart;
|
||||
private int mSelectionEnd;
|
||||
|
||||
public ReactTextInputSelectionEvent(
|
||||
int viewId,
|
||||
long timestampMs,
|
||||
int selectionStart,
|
||||
int selectionEnd) {
|
||||
super(viewId, timestampMs);
|
||||
mSelectionStart = selectionStart;
|
||||
mSelectionEnd = selectionEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return EVENT_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch(RCTEventEmitter rctEventEmitter) {
|
||||
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData());
|
||||
}
|
||||
|
||||
private WritableMap serializeEventData() {
|
||||
WritableMap eventData = Arguments.createMap();
|
||||
|
||||
WritableMap selectionData = Arguments.createMap();
|
||||
selectionData.putInt("start", mSelectionStart);
|
||||
selectionData.putInt("end", mSelectionEnd);
|
||||
|
||||
eventData.putMap("selection", selectionData);
|
||||
return eventData;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) 2015-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;
|
||||
|
||||
/**
|
||||
* Implement this interface to be informed of selection changes in the ReactTextEdit
|
||||
* This is used by the ReactTextInputManager to forward events from the EditText to JS
|
||||
*/
|
||||
interface SelectionWatcher {
|
||||
public void onSelectionChanged(int start, int end);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user