Fix EditText cursor when line spacing is set
Test: bit FrameworksCoreTests:android.widget.TextViewTest
Test: bit FrameworksCoreTests:android.widget.EditorCursorTest
Test: bit CtsWidgetTestCases:android.widget.cts.TextViewTest
Test: bit CtsWidgetTestCases:android.widget.cts.EditTextTest
Bug: 30870806
Change-Id: I54f014b06af328c3e9a9c4ddb5a3348a26e290c2
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2dc3f60..2c84ba0 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1451,6 +1451,16 @@
}
/**
+ * Return the vertical position of the bottom of the specified line without the line spacing
+ * added.
+ *
+ * @hide
+ */
+ public final int getLineBottomWithoutSpacing(int line) {
+ return getLineTop(line + 1) - getLineExtra(line);
+ }
+
+ /**
* Return the vertical position of the baseline of the specified line.
*/
public final int getLineBaseline(int line) {
@@ -1593,13 +1603,12 @@
* but can be multiple discontinuous lines in text with multiple
* directionalities.
*/
- public void getCursorPath(int point, Path dest,
- CharSequence editingBuffer) {
+ public void getCursorPath(final int point, final Path dest, final CharSequence editingBuffer) {
dest.reset();
int line = getLineForOffset(point);
int top = getLineTop(line);
- int bottom = getLineTop(line+1);
+ int bottom = getLineBottomWithoutSpacing(line);
boolean clamped = shouldClampCursor(line);
float h1 = getPrimaryHorizontal(point, clamped) - 0.5f;
@@ -1719,11 +1728,11 @@
start = temp;
}
- int startline = getLineForOffset(start);
- int endline = getLineForOffset(end);
+ final int startline = getLineForOffset(start);
+ final int endline = getLineForOffset(end);
int top = getLineTop(startline);
- int bottom = getLineBottom(endline);
+ int bottom = getLineBottomWithoutSpacing(endline);
if (startline == endline) {
addSelection(startline, start, end, top, bottom, dest);
@@ -1747,10 +1756,9 @@
}
top = getLineTop(endline);
- bottom = getLineBottom(endline);
+ bottom = getLineBottomWithoutSpacing(endline);
- addSelection(endline, getLineStart(endline), end,
- top, bottom, dest);
+ addSelection(endline, getLineStart(endline), end, top, bottom, dest);
if (getParagraphDirection(endline) == DIR_RIGHT_TO_LEFT)
dest.addRect(width, top, getLineRight(endline), bottom, Path.Direction.CW);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 0d02444..f008570 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1917,7 +1917,7 @@
final int offset = mTextView.getSelectionStart();
final int line = layout.getLineForOffset(offset);
final int top = layout.getLineTop(line);
- final int bottom = layout.getLineTop(line + 1);
+ final int bottom = layout.getLineBottomWithoutSpacing(line);
mCursorCount = layout.isLevelBoundary(offset) ? 2 : 1;
@@ -2985,7 +2985,8 @@
@Override
protected int getVerticalLocalPosition(int line) {
- return mTextView.getLayout().getLineBottom(line);
+ final Layout layout = mTextView.getLayout();
+ return layout.getLineBottomWithoutSpacing(line);
}
@Override
@@ -3642,7 +3643,8 @@
@Override
protected int getVerticalLocalPosition(int line) {
- return mTextView.getLayout().getLineBottom(line) - mContainerMarginTop;
+ final Layout layout = mTextView.getLayout();
+ return layout.getLineBottomWithoutSpacing(line) - mContainerMarginTop;
}
@Override
@@ -4032,7 +4034,7 @@
primaryHorizontal,
layout.getLineTop(line),
primaryHorizontal,
- layout.getLineTop(line + 1) + mHandleHeight);
+ layout.getLineBottom(line) - layout.getLineBottom(line) + mHandleHeight);
}
// Take TextView's padding and scroll into account.
int textHorizontalOffset = mTextView.viewportToContentHorizontalOffset();
@@ -4127,7 +4129,7 @@
+ viewportToContentVerticalOffset;
final float insertionMarkerBaseline = layout.getLineBaseline(line)
+ viewportToContentVerticalOffset;
- final float insertionMarkerBottom = layout.getLineBottom(line)
+ final float insertionMarkerBottom = layout.getLineBottomWithoutSpacing(line)
+ viewportToContentVerticalOffset;
final boolean isTopVisible = mTextView
.isPositionVisible(insertionMarkerX, insertionMarkerTop);
@@ -4395,7 +4397,7 @@
mPositionX = getCursorHorizontalPosition(layout, offset) - mHotspotX
- getHorizontalOffset() + getCursorOffset();
- mPositionY = layout.getLineBottom(line);
+ mPositionY = layout.getLineBottomWithoutSpacing(line);
// Take TextView's padding and scroll into account.
mPositionX += mTextView.viewportToContentHorizontalOffset();