Implement TextNodeRegion

Summary: NodeRegion is only able to describe a rectangular region for touch, which is not good enough for text, where we want to be able to assign different touch ids to individual words (and those can span more than one line and in general have non-rectangular structure). This diff adds TextNodeRegion which inserts additional markers into text Layout to allow individual words to have unique react tags.

Reviewed By: ahmedre

Differential Revision: D2757387
This commit is contained in:
Denis Koroskin
2015-12-17 13:52:12 -08:00
committed by Ahmed El-Helw
parent 85cdfcd1f7
commit 381bf1b76f
10 changed files with 143 additions and 45 deletions
@@ -0,0 +1,47 @@
/**
* 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.flat;
import android.text.Layout;
import android.text.Spanned;
/* package */ final class TextNodeRegion extends NodeRegion {
private final Layout mLayout;
TextNodeRegion(float left, float top, float right, float bottom, int tag, Layout layout) {
super(left, top, right, bottom, tag);
mLayout = layout;
}
/* package */ 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.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);
if (link.length != 0) {
return link[0].getReactTag();
}
}
}
return super.getReactTag(touchX, touchY);
}
}