summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt6
-rw-r--r--core/java/android/text/Selection.java95
-rw-r--r--core/java/android/text/method/ArrowKeyMovementMethod.java21
-rw-r--r--core/java/android/text/method/BaseMovementMethod.java29
4 files changed, 151 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index dc5466100265..1cd8253aac36 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -45247,6 +45247,8 @@ package android.text {
method public static boolean extendRight(android.text.Spannable, android.text.Layout);
method public static final void extendSelection(android.text.Spannable, int);
method public static boolean extendToLeftEdge(android.text.Spannable, android.text.Layout);
+ method public static boolean extendToParagraphEnd(@NonNull android.text.Spannable);
+ method public static boolean extendToParagraphStart(@NonNull android.text.Spannable);
method public static boolean extendToRightEdge(android.text.Spannable, android.text.Layout);
method public static boolean extendUp(android.text.Spannable, android.text.Layout);
method public static final int getSelectionEnd(CharSequence);
@@ -45255,6 +45257,8 @@ package android.text {
method public static boolean moveLeft(android.text.Spannable, android.text.Layout);
method public static boolean moveRight(android.text.Spannable, android.text.Layout);
method public static boolean moveToLeftEdge(android.text.Spannable, android.text.Layout);
+ method public static boolean moveToParagraphEnd(@NonNull android.text.Spannable, @NonNull android.text.Layout);
+ method public static boolean moveToParagraphStart(@NonNull android.text.Spannable, @NonNull android.text.Layout);
method public static boolean moveToRightEdge(android.text.Spannable, android.text.Layout);
method public static boolean moveUp(android.text.Spannable, android.text.Layout);
method public static final void removeSelection(android.text.Spannable);
@@ -45703,6 +45707,7 @@ package android.text.method {
method protected boolean left(android.widget.TextView, android.text.Spannable);
method protected boolean lineEnd(android.widget.TextView, android.text.Spannable);
method protected boolean lineStart(android.widget.TextView, android.text.Spannable);
+ method public boolean nextParagraph(@NonNull android.widget.TextView, @NonNull android.text.Spannable);
method public boolean onGenericMotionEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
method public boolean onKeyDown(android.widget.TextView, android.text.Spannable, int, android.view.KeyEvent);
method public boolean onKeyOther(android.widget.TextView, android.text.Spannable, android.view.KeyEvent);
@@ -45712,6 +45717,7 @@ package android.text.method {
method public boolean onTrackballEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
method protected boolean pageDown(android.widget.TextView, android.text.Spannable);
method protected boolean pageUp(android.widget.TextView, android.text.Spannable);
+ method public boolean previousParagraph(@NonNull android.widget.TextView, @NonNull android.text.Spannable);
method protected boolean right(android.widget.TextView, android.text.Spannable);
method protected boolean top(android.widget.TextView, android.text.Spannable);
method protected boolean up(android.widget.TextView, android.text.Spannable);
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 57c1d237d4ed..6a54d2378f6c 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -16,6 +16,7 @@
package android.text;
+import android.annotation.NonNull;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
@@ -346,6 +347,100 @@ public class Selection {
return false;
}
+ private static final char PARAGRAPH_SEPARATOR = '\n';
+
+ /**
+ * Move the cusrot to the closest paragraph start offset.
+ *
+ * @param text the spannable text
+ * @param layout layout to be used for drawing.
+ * @return true if the cursor is moved, otherwise false.
+ */
+ public static boolean moveToParagraphStart(@NonNull Spannable text, @NonNull Layout layout) {
+ int start = getSelectionStart(text);
+ int end = getSelectionEnd(text);
+
+ if (start != end) {
+ setSelection(text, chooseHorizontal(layout, -1, start, end));
+ return true;
+ } else {
+ int to = TextUtils.lastIndexOf(text, PARAGRAPH_SEPARATOR, start - 1);
+ if (to == -1) {
+ to = 0; // If not found, use the document start offset as a paragraph start.
+ }
+ if (to != end) {
+ setSelection(text, to);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Move the cursor to the closest paragraph end offset.
+ *
+ * @param text the spannable text
+ * @param layout layout to be used for drawing.
+ * @return true if the cursor is moved, otherwise false.
+ */
+ public static boolean moveToParagraphEnd(@NonNull Spannable text, @NonNull Layout layout) {
+ int start = getSelectionStart(text);
+ int end = getSelectionEnd(text);
+
+ if (start != end) {
+ setSelection(text, chooseHorizontal(layout, 1, start, end));
+ return true;
+ } else {
+ int to = TextUtils.indexOf(text, PARAGRAPH_SEPARATOR, end + 1);
+ if (to == -1) {
+ to = text.length();
+ }
+ if (to != end) {
+ setSelection(text, to);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Extend the selection to the closest paragraph start offset.
+ *
+ * @param text the spannable text
+ * @return true if the selection is extended, otherwise false
+ */
+ public static boolean extendToParagraphStart(@NonNull Spannable text) {
+ int end = getSelectionEnd(text);
+ int to = TextUtils.lastIndexOf(text, PARAGRAPH_SEPARATOR, end - 1);
+ if (to == -1) {
+ to = 0; // If not found, use the document start offset as a paragraph start.
+ }
+ if (to != end) {
+ extendSelection(text, to);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Extend the selection to the closest paragraph end offset.
+ *
+ * @param text the spannable text
+ * @return true if the selection is extended, otherwise false
+ */
+ public static boolean extendToParagraphEnd(@NonNull Spannable text) {
+ int end = getSelectionEnd(text);
+ int to = TextUtils.indexOf(text, PARAGRAPH_SEPARATOR, end + 1);
+ if (to == -1) {
+ to = text.length();
+ }
+ if (to != end) {
+ extendSelection(text, to);
+ return true;
+ }
+ return false;
+ }
+
/**
* Move the selection end to the buffer offset physically above
* the current selection end.
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 57fe1315ab5d..d3367d014e7d 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -16,6 +16,7 @@
package android.text.method;
+import android.annotation.NonNull;
import android.graphics.Rect;
import android.text.Layout;
import android.text.Selection;
@@ -222,6 +223,26 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme
}
@Override
+ public boolean previousParagraph(@NonNull TextView widget, @NonNull Spannable buffer) {
+ final Layout layout = widget.getLayout();
+ if (isSelecting(buffer)) {
+ return Selection.extendToParagraphStart(buffer);
+ } else {
+ return Selection.moveToParagraphStart(buffer, layout);
+ }
+ }
+
+ @Override
+ public boolean nextParagraph(@NonNull TextView widget, @NonNull Spannable buffer) {
+ final Layout layout = widget.getLayout();
+ if (isSelecting(buffer)) {
+ return Selection.extendToParagraphEnd(buffer);
+ } else {
+ return Selection.moveToParagraphEnd(buffer, layout);
+ }
+ }
+
+ @Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
int initialScrollX = -1;
int initialScrollY = -1;
diff --git a/core/java/android/text/method/BaseMovementMethod.java b/core/java/android/text/method/BaseMovementMethod.java
index 155a2c4fcfa0..7a4b3a095ae9 100644
--- a/core/java/android/text/method/BaseMovementMethod.java
+++ b/core/java/android/text/method/BaseMovementMethod.java
@@ -16,6 +16,7 @@
package android.text.method;
+import android.annotation.NonNull;
import android.text.Layout;
import android.text.Spannable;
import android.view.InputDevice;
@@ -190,6 +191,9 @@ public class BaseMovementMethod implements MovementMethod {
} else if (KeyEvent.metaStateHasModifiers(movementMetaState,
KeyEvent.META_ALT_ON)) {
return top(widget, buffer);
+ } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+ KeyEvent.META_CTRL_ON)) {
+ return previousParagraph(widget, buffer);
}
break;
@@ -199,6 +203,9 @@ public class BaseMovementMethod implements MovementMethod {
} else if (KeyEvent.metaStateHasModifiers(movementMetaState,
KeyEvent.META_ALT_ON)) {
return bottom(widget, buffer);
+ } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+ KeyEvent.META_CTRL_ON)) {
+ return nextParagraph(widget, buffer);
}
break;
@@ -399,6 +406,28 @@ public class BaseMovementMethod implements MovementMethod {
return false;
}
+ /**
+ * Performs a previous paragraph movement action.
+ *
+ * @param widget the text view
+ * @param buffer the text buffer
+ * @return true if the event was handled, otherwise false.
+ */
+ public boolean previousParagraph(@NonNull TextView widget, @NonNull Spannable buffer) {
+ return false;
+ }
+
+ /**
+ * Performs a next paragraph movement action.
+ *
+ * @param widget the text view
+ * @param buffer the text buffer
+ * @return true if the event was handled, otherwise false.
+ */
+ public boolean nextParagraph(@NonNull TextView widget, @NonNull Spannable buffer) {
+ return false;
+ }
+
private int getTopLine(TextView widget) {
return widget.getLayout().getLineForVertical(widget.getScrollY());
}