Skip to content

Commit

Permalink
enhance onSelectionChange in TextInput with cursorPositionX/Y
Browse files Browse the repository at this point in the history
  • Loading branch information
perunt committed Apr 21, 2023
1 parent 33ce1f4 commit eddebe6
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ - (RCTTextSelection *)selection
initWithStart:[backedTextInputView offsetFromPosition:backedTextInputView.beginningOfDocument
toPosition:selectedTextRange.start]
end:[backedTextInputView offsetFromPosition:backedTextInputView.beginningOfDocument
toPosition:selectedTextRange.end]];
toPosition:selectedTextRange.end]
cursorPosition:[backedTextInputView caretRectForPosition:selectedTextRange.start].origin];
}

- (void)setSelection:(RCTTextSelection *)selection
Expand Down Expand Up @@ -519,6 +520,8 @@ - (void)textInputDidChangeSelection
@"selection" : @{
@"start" : @(selection.start),
@"end" : @(selection.end),
@"positionY": @(selectionOrigin.y),
@"positionX": @(selectionOrigin.x),
},
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@

@property (nonatomic, assign, readonly) NSInteger start;
@property (nonatomic, assign, readonly) NSInteger end;
@property (nonatomic, assign, readonly) CGPoint cursorPosition;

- (instancetype)initWithStart:(NSInteger)start end:(NSInteger)end;
- (instancetype)initWithStart:(NSInteger)start end:(NSInteger)end cursorPosition:(CGPoint)cursorPosition;

@end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

@implementation RCTTextSelection

- (instancetype)initWithStart:(NSInteger)start end:(NSInteger)end
- (instancetype)initWithStart:(NSInteger)start end:(NSInteger)end cursorPosition:(CGPoint)cursorPosition
{
if (self = [super init]) {
_start = start;
_end = end;
_cursorPosition = cursorPosition;
}
return self;
}
Expand All @@ -27,7 +28,13 @@ + (RCTTextSelection *)RCTTextSelection:(id)json
if ([json isKindOfClass:[NSDictionary class]]) {
NSInteger start = [self NSInteger:json[@"start"]];
NSInteger end = [self NSInteger:json[@"end"]];
return [[RCTTextSelection alloc] initWithStart:start end:end];
CGPoint cursorPosition = CGPointMake(
[self CGFloat:json[@"cursorPositionX"]],
[self CGFloat:json[@"cursorPositionY"]]
);
return [[RCTTextSelection alloc] initWithStart:start
end:end
cursorPosition:cursorPosition];
}

return nil;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
import android.view.ViewTreeObserver;

/** Manages instances of TextInput. */
@ReactModule(name = ReactTextInputManager.REACT_CLASS)
Expand Down Expand Up @@ -1240,6 +1241,24 @@ public ReactSelectionWatcher(ReactEditText editText) {

@Override
public void onSelectionChanged(int start, int end) {
// Calculate cursor position
Layout layout = mReactEditText.getLayout();
if (mReactEditText.getLayout() == null) {
mReactEditText.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mReactEditText.getViewTreeObserver().removeOnGlobalLayoutListener(this);
onSelectionChanged(start, end);
}
});
return;
}

int line = layout.getLineForOffset(start);
int baseline = layout.getLineBaseline(line);
int ascent = layout.getLineAscent(line);
float cursorPositionX = layout.getPrimaryHorizontal(start);
float cursorPositionY = baseline + ascent;
// 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
Expand All @@ -1252,7 +1271,12 @@ public void onSelectionChanged(int start, int end) {
if (mPreviousSelectionStart != realStart || mPreviousSelectionEnd != realEnd) {
mEventDispatcher.dispatchEvent(
new ReactTextInputSelectionEvent(
mSurfaceId, mReactEditText.getId(), realStart, realEnd));
mSurfaceId,
mReactEditText.getId(),
realStart,
realEnd,
Math.round(PixelUtil.toDIPFromPixel(cursorPositionX)),
Math.round(PixelUtil.toDIPFromPixel(cursorPositionY))));

mPreviousSelectionStart = realStart;
mPreviousSelectionEnd = realEnd;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,31 @@

private int mSelectionStart;
private int mSelectionEnd;
private float mCursorPositionX;
private float mCursorPositionY;

@Deprecated
public ReactTextInputSelectionEvent(int viewId, int selectionStart, int selectionEnd) {
this(-1, viewId, selectionStart, selectionEnd);
public ReactTextInputSelectionEvent(
int viewId,
int selectionStart,
int selectionEnd,
float cursorPositionX,
float cursorPositionY) {
this(-1, viewId, selectionStart, selectionEnd, cursorPositionX, cursorPositionY);
}

public ReactTextInputSelectionEvent(
int surfaceId, int viewId, int selectionStart, int selectionEnd) {
int surfaceId,
int viewId,
int selectionStart,
int selectionEnd,
float cursorPositionX,
float cursorPositionY) {
super(surfaceId, viewId);
mSelectionStart = selectionStart;
mSelectionEnd = selectionEnd;
mCursorPositionX = cursorPositionX;
mCursorPositionY = cursorPositionY;
}

@Override
Expand All @@ -45,6 +59,8 @@ protected WritableMap getEventData() {
WritableMap selectionData = Arguments.createMap();
selectionData.putInt("end", mSelectionEnd);
selectionData.putInt("start", mSelectionStart);
selectionData.putDouble("cursorPositionX", mCursorPositionX);
selectionData.putDouble("cursorPositionY", mCursorPositionY);

eventData.putMap("selection", selectionData);
return eventData;
Expand Down

0 comments on commit eddebe6

Please sign in to comment.