diff options
| author | 2022-11-11 16:13:29 -0800 | |
|---|---|---|
| committer | 2022-12-02 15:26:49 -0800 | |
| commit | edff783dee2060a8f49e13df47a101b15b4f547c (patch) | |
| tree | 4f44666c80f38493935942c5e4f74144a168f59d | |
| parent | 7c5817e876c62f3237a2b94622c55b21340e846e (diff) | |
Text highlighting for select and delete gesture previews
If there is a selection or deletion preview range set, then the corresponding highlight will be displayed, and the cursor or regular selection highlight will be hidden. Once the selection or deletion preview range is cleared, then the cursor or regular selection highlight will be displayed again.
Bug: 240436893
Test: atest android.widget.cts.TextViewHandwritingGestureTest
Change-Id: I30285942396a11b5b38a9e83ee13e7c0485baa7d
| -rw-r--r-- | core/java/android/widget/Editor.java | 5 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 80 |
2 files changed, 82 insertions, 3 deletions
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 558d96089bb7..0a3ea8a9f356 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -2082,7 +2082,8 @@ public class Editor { } if (selectionHighlight != null && selectionStart == selectionEnd - && mDrawableForCursor != null) { + && mDrawableForCursor != null + && !mTextView.hasGesturePreviewHighlight()) { drawCursor(canvas, cursorOffsetVertical); // Rely on the drawable entirely, do not draw the cursor line. // Has to be done after the IMM related code above which relies on the highlight. @@ -2714,7 +2715,7 @@ public class Editor { unregisterOnBackInvokedCallback(); } - private void stopTextActionModeWithPreservingSelection() { + void stopTextActionModeWithPreservingSelection() { if (mTextActionMode != null) { mRestartActionModeOnNextRefresh = true; } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 475a8491de4d..7e7f9c99b948 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -68,6 +68,7 @@ import android.content.res.XmlResourceParser; import android.graphics.BaseCanvas; import android.graphics.BlendMode; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.Paint; @@ -222,6 +223,7 @@ import android.widget.RemoteViews.RemoteView; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.graphics.ColorUtils; import com.android.internal.inputmethod.EditableInputConnection; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -931,6 +933,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private List<Path> mHighlightPaths; private List<Paint> mHighlightPaints; private Highlights mHighlights; + private int mGesturePreviewHighlightStart = -1; + private int mGesturePreviewHighlightEnd = -1; + private Paint mGesturePreviewHighlightPaint; private final List<Path> mPathRecyclePool = new ArrayList<>(); private boolean mHighlightPathsBogus = true; @@ -6167,6 +6172,59 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * Highlights the text range (from inclusive start offset to exclusive end offset) to show what + * will be selected by the ongoing select handwriting gesture. While the gesture preview + * highlight is shown, the selection or cursor is hidden. If the text or selection is changed, + * the gesture preview highlight will be cleared. + */ + private void setSelectGesturePreviewHighlight(int start, int end) { + // Selection preview highlight color is the same as selection highlight color. + setGesturePreviewHighlight(start, end, mHighlightColor); + } + + /** + * Highlights the text range (from inclusive start offset to exclusive end offset) to show what + * will be deleted by the ongoing delete handwriting gesture. While the gesture preview + * highlight is shown, the selection or cursor is hidden. If the text or selection is changed, + * the gesture preview highlight will be cleared. + */ + private void setDeleteGesturePreviewHighlight(int start, int end) { + // Deletion preview highlight color is 20% opacity of the default text color. + int color = mTextColor.getDefaultColor(); + color = ColorUtils.setAlphaComponent(color, (int) (0.2f * Color.alpha(color))); + setGesturePreviewHighlight(start, end, color); + } + + private void setGesturePreviewHighlight(int start, int end, int color) { + mGesturePreviewHighlightStart = start; + mGesturePreviewHighlightEnd = end; + if (mGesturePreviewHighlightPaint == null) { + mGesturePreviewHighlightPaint = new Paint(); + mGesturePreviewHighlightPaint.setStyle(Paint.Style.FILL); + } + mGesturePreviewHighlightPaint.setColor(color); + + if (mEditor != null) { + mEditor.hideCursorAndSpanControllers(); + mEditor.stopTextActionModeWithPreservingSelection(); + } + + mHighlightPathsBogus = true; + invalidate(); + } + + private void clearGesturePreviewHighlight() { + mGesturePreviewHighlightStart = -1; + mGesturePreviewHighlightEnd = -1; + mHighlightPathsBogus = true; + invalidate(); + } + + boolean hasGesturePreviewHighlight() { + return mGesturePreviewHighlightStart > 0; + } + + /** * Convenience method to append the specified text to the TextView's * display buffer, upgrading it to {@link android.widget.TextView.BufferType#EDITABLE} * if it was not already editable. @@ -8300,6 +8358,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } } + + if (hasGesturePreviewHighlight()) { + final Path path; + if (mPathRecyclePool.isEmpty()) { + path = new Path(); + } else { + path = mPathRecyclePool.get(mPathRecyclePool.size() - 1); + mPathRecyclePool.remove(mPathRecyclePool.size() - 1); + path.reset(); + } + mLayout.getSelectionPath( + mGesturePreviewHighlightStart, mGesturePreviewHighlightEnd, path); + mHighlightPaths.add(path); + mHighlightPaints.add(mGesturePreviewHighlightPaint); + } + mHighlightPathsBogus = false; } @@ -8503,7 +8577,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int cursorOffsetVertical = voffsetCursor - voffsetText; maybeUpdateHighlightPaths(); - Path highlight = getUpdatedHighlightPath(); + // If there is a gesture preview highlight, then the selection or cursor is not drawn. + Path highlight = hasGesturePreviewHighlight() ? null : getUpdatedHighlightPath(); if (mEditor != null) { mEditor.onDraw(canvas, layout, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint, cursorOffsetVertical); @@ -11699,6 +11774,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener resetErrorChangedFlag(); sendOnTextChanged(buffer, start, before, after); onTextChanged(buffer, start, before, after); + + clearGesturePreviewHighlight(); } /** @@ -11737,6 +11814,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (selChanged) { + clearGesturePreviewHighlight(); mHighlightPathBogus = true; if (mEditor != null && !isFocused()) mEditor.mSelectionMoved = true; |