Merge "Text handles movement improvements."

This commit is contained in:
Gilles Debunne
2011-02-24 10:29:22 -08:00
committed by Android (Google) Code Review

View File

@@ -8655,9 +8655,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private float mTouchToWindowOffsetX;
private float mTouchToWindowOffsetY;
private float mHotspotX;
private float mHotspotY;
private int mHeight;
// Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up
private float mTouchOffsetY;
// Where the touch position should be on the handle to ensure a maximum cursor visibility
private float mIdealVerticalOffset;
private int mLastParentX;
private int mLastParentY;
private float mDownPositionX, mDownPositionY;
@@ -8767,7 +8769,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int handleHeight = mDrawable.getIntrinsicHeight();
mTouchOffsetY = -handleHeight * 0.3f;
mHotspotY = 0;
mIdealVerticalOffset = 0.7f * handleHeight;
mHeight = handleHeight;
invalidate();
}
@@ -8836,7 +8838,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int[] coords = mTempCoords;
hostView.getLocationInWindow(coords);
final int posX = coords[0] + mPositionX + (int) mHotspotX;
final int posY = coords[1] + mPositionY + (int) mHotspotY;
final int posY = coords[1] + mPositionY;
// Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
return posX >= clip.left - 1 && posX <= clip.right + 1 &&
@@ -8901,6 +8903,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mDownPositionY = ev.getRawY();
mTouchToWindowOffsetX = mDownPositionX - mPositionX;
mTouchToWindowOffsetY = mDownPositionY - mPositionY;
final int[] coords = mTempCoords;
TextView.this.getLocationInWindow(coords);
mLastParentX = coords[0];
@@ -8915,8 +8918,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
case MotionEvent.ACTION_MOVE: {
final float rawX = ev.getRawX();
final float rawY = ev.getRawY();
// Vertical hysteresis: vertical down movement tends to snap to ideal offset
final float previousVerticalOffset = mTouchToWindowOffsetY - mLastParentY;
final float currentVerticalOffset = rawY - mPositionY - mLastParentY;
float newVerticalOffset;
if (previousVerticalOffset < mIdealVerticalOffset) {
newVerticalOffset = Math.min(currentVerticalOffset, mIdealVerticalOffset);
newVerticalOffset = Math.max(newVerticalOffset, previousVerticalOffset);
} else {
newVerticalOffset = Math.max(currentVerticalOffset, mIdealVerticalOffset);
newVerticalOffset = Math.min(newVerticalOffset, previousVerticalOffset);
}
mTouchToWindowOffsetY = newVerticalOffset + mLastParentY;
final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX;
final float newPosY = rawY - mTouchToWindowOffsetY + mHotspotY + mTouchOffsetY;
final float newPosY = rawY - mTouchToWindowOffsetY + mTouchOffsetY;
mController.updatePosition(this, Math.round(newPosX), Math.round(newPosY));
break;
@@ -8954,18 +8971,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mIsDragging;
}
void positionAtCursor(final int offset, boolean bottom) {
void positionAtCursor(final int offset) {
addPositionToTouchUpFilter(offset);
final int width = mDrawable.getIntrinsicWidth();
final int height = mDrawable.getIntrinsicHeight();
final int line = mLayout.getLineForOffset(offset);
final int lineTop = mLayout.getLineTop(line);
final int lineBottom = mLayout.getLineBottom(line);
final Rect bounds = sCursorControllerTempRect;
bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX) +
TextView.this.mScrollX;
bounds.top = (bottom ? lineBottom : lineTop - mHeight) + TextView.this.mScrollY;
bounds.top = lineBottom + TextView.this.mScrollY;
bounds.right = bounds.left + width;
bounds.bottom = bounds.top + height;
@@ -9107,10 +9123,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public void updatePosition(HandleView handle, int x, int y) {
final int previousOffset = getSelectionStart();
int offset = getHysteresisOffset(x, y, previousOffset);
final int newOffset = getOffset(x, y);
if (offset != previousOffset) {
updateOffset(handle, offset);
if (newOffset != previousOffset) {
updateOffset(handle, newOffset);
removePastePopupCallback();
}
hideDelayed();
@@ -9131,7 +9147,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return;
}
getHandle().positionAtCursor(offset, true);
getHandle().positionAtCursor(offset);
}
public int getCurrentOffset(HandleView handle) {
@@ -9215,8 +9231,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int selectionStart = getSelectionStart();
int selectionEnd = getSelectionEnd();
final int previousOffset = handle == mStartHandle ? selectionStart : selectionEnd;
int offset = getHysteresisOffset(x, y, previousOffset);
int offset = getOffset(x, y);
// Handle the case where start and end are swapped, making sure start <= end
if (handle == mStartHandle) {
@@ -9275,8 +9290,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
// The handles have been created since the controller isShowing().
mStartHandle.positionAtCursor(selectionStart, true);
mEndHandle.positionAtCursor(selectionEnd, true);
mStartHandle.positionAtCursor(selectionStart);
mEndHandle.positionAtCursor(selectionEnd);
}
public int getCurrentOffset(HandleView handle) {
@@ -9406,26 +9421,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return offset;
}
int getHysteresisOffset(int x, int y, int previousOffset) {
final Layout layout = getLayout();
if (layout == null) return -1;
int line = getLineAtCoordinate(y);
final int previousLine = layout.getLineForOffset(previousOffset);
final int previousLineTop = layout.getLineTop(previousLine);
final int previousLineBottom = layout.getLineBottom(previousLine);
final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 8;
// If new line is just before or after previous line and y position is less than
// hysteresisThreshold away from previous line, keep cursor on previous line.
if (((line == previousLine + 1) && ((y - previousLineBottom) < hysteresisThreshold)) ||
((line == previousLine - 1) && ((previousLineTop - y) < hysteresisThreshold))) {
line = previousLine;
}
return getOffsetAtCoordinate(line, x);
}
private int convertToLocalHorizontalCoordinate(int x) {
x -= getTotalPaddingLeft();
// Clamp the position to inside of the view.