Skip to content

Commit

Permalink
RCTVirtualText wasn't clickable in certain cases
Browse files Browse the repository at this point in the history
Summary:
Text in Nodes is squashed into a single DrawCommand for drawing a
Boring or StaticLayout. Touch is handled using a TextNodeRegion subclass of
NodeRegion that knows how to identify pieces of text inside of the DrawCommand
based on spans in the text. However, we only use a TextNodeRegion on the
second call for updateNodeRegion for an RCTText. If there is only one call,
the NodeRegion will just be a normal one. This patch ensures that the
NodeRegion for an RCTText is always a TextNodeRegion, allowing for null
Layouts that are set when the DrawCommand is made.

Reviewed By: astreet

Differential Revision: D3291682
  • Loading branch information
Ahmed El-Helw committed Dec 19, 2016
1 parent 9d67989 commit c62840c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 15 deletions.
17 changes: 15 additions & 2 deletions ReactAndroid/src/main/java/com/facebook/react/flat/RCTText.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ protected void collectState(
return;
}

boolean updateNodeRegion = false;
if (mDrawCommand == null) {
// Layout was not created during the measure pass, must be Boring, create it now
mDrawCommand = new DrawTextLayout(new BoringLayout(
Expand All @@ -190,6 +191,7 @@ protected void collectState(
mSpacingAdd,
mBoringLayoutMetrics,
INCLUDE_PADDING));
updateNodeRegion = true;
}

Spacing padding = getPadding();
Expand All @@ -212,6 +214,13 @@ protected void collectState(
clipBottom);
stateBuilder.addDrawCommand(mDrawCommand);

if (updateNodeRegion) {
NodeRegion nodeRegion = getNodeRegion();
if (nodeRegion instanceof TextNodeRegion) {
((TextNodeRegion) nodeRegion).setLayout(mDrawCommand.getLayout());
}
}

performCollectAttachDetachListeners(stateBuilder);
}

Expand Down Expand Up @@ -240,12 +249,16 @@ public void setNumberOfLines(int numberOfLines) {
float right,
float bottom,
boolean isVirtual) {

NodeRegion nodeRegion = getNodeRegion();
if (mDrawCommand == null) {
super.updateNodeRegion(left, top, right, bottom, isVirtual);
if (nodeRegion.mLeft != left || nodeRegion.mTop != top || nodeRegion.mRight != right ||
nodeRegion.mBottom != bottom || nodeRegion.mIsVirtual != isVirtual) {
setNodeRegion(new TextNodeRegion(left, top, right, bottom, getReactTag(), isVirtual, null));
}
return;
}

NodeRegion nodeRegion = getNodeRegion();
Layout layout = null;

if (nodeRegion instanceof TextNodeRegion) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@

package com.facebook.react.flat;

import javax.annotation.Nullable;

import android.text.Layout;
import android.text.Spanned;

/* package */ final class TextNodeRegion extends NodeRegion {
private final Layout mLayout;
private @Nullable Layout mLayout;

/* package */ TextNodeRegion(
float left,
Expand All @@ -22,29 +24,35 @@
float bottom,
int tag,
boolean isVirtual,
Layout layout) {
@Nullable Layout layout) {
super(left, top, right, bottom, tag, isVirtual);
mLayout = layout;
}

/* package */ Layout getLayout() {
public void setLayout(Layout layout) {
mLayout = layout;
}

/* package */ @Nullable Layout getLayout() {
return mLayout;
}

/* package */ int getReactTag(float touchX, float touchY) {
int y = Math.round(touchY - mTop);
if (y >= mLayout.getLineTop(0) && y < mLayout.getLineBottom(mLayout.getLineCount() - 1)) {
float x = Math.round(touchX - mLeft);
int line = mLayout.getLineForVertical(y);
if (mLayout != null) {
int y = Math.round(touchY - mTop);
if (y >= mLayout.getLineTop(0) && y < mLayout.getLineBottom(mLayout.getLineCount() - 1)) {
float x = Math.round(touchX - mLeft);
int line = mLayout.getLineForVertical(y);

if (mLayout.getLineLeft(line) <= x && x <= mLayout.getLineRight(line)) {
int off = mLayout.getOffsetForHorizontal(line, x);
if (mLayout.getLineLeft(line) <= x && x <= mLayout.getLineRight(line)) {
int off = mLayout.getOffsetForHorizontal(line, x);

Spanned text = (Spanned) mLayout.getText();
RCTRawText[] link = text.getSpans(off, off, RCTRawText.class);
Spanned text = (Spanned) mLayout.getText();
RCTRawText[] link = text.getSpans(off, off, RCTRawText.class);

if (link.length != 0) {
return link[0].getReactTag();
if (link.length != 0) {
return link[0].getReactTag();
}
}
}
}
Expand Down

0 comments on commit c62840c

Please sign in to comment.