Skip to content

Commit 64901d4

Browse files
author
Gilles Debunne
committed
Better handles' visibility test
Checking if the hotspot position is visible instead of checking if it is part of the clipped visible rectangle. Bug 5638710 Patch set 2: synchronize static variables you will. Patch set 3: renaming and refactored the while loop. Patch set 4: synchronize you will (again) Patch set 5: parent Change-Id: I330510f491c85f910fc61598936113ad07d304e4
1 parent 88f10c6 commit 64901d4

File tree

1 file changed

+48
-30
lines changed

1 file changed

+48
-30
lines changed

core/java/android/widget/TextView.java

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9370,40 +9370,57 @@ private void updatePosition() {
93709370
mPositionY = mTempCoords[1];
93719371
}
93729372

9373-
public boolean isVisible(int positionX, int positionY) {
9374-
final TextView textView = TextView.this;
9373+
public void onScrollChanged() {
9374+
mScrollHasChanged = true;
9375+
}
9376+
}
93759377

9376-
if (mTempRect == null) mTempRect = new Rect();
9377-
final Rect clip = mTempRect;
9378-
clip.left = getCompoundPaddingLeft();
9379-
clip.top = getExtendedPaddingTop();
9380-
clip.right = textView.getWidth() - getCompoundPaddingRight();
9381-
clip.bottom = textView.getHeight() - getExtendedPaddingBottom();
9382-
9383-
final ViewParent parent = textView.getParent();
9384-
if (parent == null || !parent.getChildVisibleRect(textView, clip, null)) {
9385-
return false;
9386-
}
9378+
public boolean isPositionVisible(int positionX, int positionY) {
9379+
synchronized (sTmpPosition) {
9380+
final float[] position = sTmpPosition;
9381+
position[0] = positionX;
9382+
position[1] = positionY;
9383+
View view = this;
93879384

9388-
int posX = mPositionX + positionX;
9389-
int posY = mPositionY + positionY;
9385+
while (view != null) {
9386+
if (view != this) {
9387+
// Local scroll is already taken into account in positionX/Y
9388+
position[0] -= view.getScrollX();
9389+
position[1] -= view.getScrollY();
9390+
}
93909391

9391-
// Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
9392-
return posX >= clip.left - 1 && posX <= clip.right + 1 &&
9393-
posY >= clip.top && posY <= clip.bottom;
9394-
}
9392+
if (position[0] < 0 || position[1] < 0 ||
9393+
position[0] > view.getWidth() || position[1] > view.getHeight()) {
9394+
return false;
9395+
}
93959396

9396-
public boolean isOffsetVisible(int offset) {
9397-
final int line = mLayout.getLineForOffset(offset);
9398-
final int lineBottom = mLayout.getLineBottom(line);
9399-
final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
9400-
return isVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
9401-
lineBottom + viewportToContentVerticalOffset());
9402-
}
9397+
if (!view.getMatrix().isIdentity()) {
9398+
view.getMatrix().mapPoints(position);
9399+
}
94039400

9404-
public void onScrollChanged() {
9405-
mScrollHasChanged = true;
9401+
position[0] += view.getLeft();
9402+
position[1] += view.getTop();
9403+
9404+
final ViewParent parent = view.getParent();
9405+
if (parent instanceof View) {
9406+
view = (View) parent;
9407+
} else {
9408+
// We've reached the ViewRoot, stop iterating
9409+
view = null;
9410+
}
9411+
}
94069412
}
9413+
9414+
// We've been able to walk up the view hierarchy and the position was never clipped
9415+
return true;
9416+
}
9417+
9418+
public boolean isOffsetVisible(int offset) {
9419+
final int line = mLayout.getLineForOffset(offset);
9420+
final int lineBottom = mLayout.getLineBottom(line);
9421+
final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
9422+
return isPositionVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
9423+
lineBottom + viewportToContentVerticalOffset());
94079424
}
94089425

94099426
@Override
@@ -9504,7 +9521,7 @@ public void hide() {
95049521
public void updatePosition(int parentPositionX, int parentPositionY,
95059522
boolean parentPositionChanged, boolean parentScrolled) {
95069523
// Either parentPositionChanged or parentScrolled is true, check if still visible
9507-
if (isShowing() && getPositionListener().isOffsetVisible(getTextOffset())) {
9524+
if (isShowing() && isOffsetVisible(getTextOffset())) {
95089525
if (parentScrolled) computeLocalPosition();
95099526
updatePosition(parentPositionX, parentPositionY);
95109527
} else {
@@ -10528,7 +10545,7 @@ private boolean isVisible() {
1052810545
return false;
1052910546
}
1053010547

10531-
return getPositionListener().isVisible(mPositionX + mHotspotX, mPositionY);
10548+
return TextView.this.isPositionVisible(mPositionX + mHotspotX, mPositionY);
1053210549
}
1053310550

1053410551
public abstract int getCurrentCursorOffset();
@@ -11510,6 +11527,7 @@ protected void replaceText_internal(int start, int end, CharSequence text) {
1151011527
private Path mHighlightPath;
1151111528
private boolean mHighlightPathBogus = true;
1151211529
private static final RectF sTempRect = new RectF();
11530+
private static final float[] sTmpPosition = new float[2];
1151311531

1151411532
// XXX should be much larger
1151511533
private static final int VERY_WIDE = 1024*1024;

0 commit comments

Comments
 (0)