diff options
| author | 2022-11-11 16:14:28 -0800 | |
|---|---|---|
| committer | 2022-12-02 17:13:07 -0800 | |
| commit | 691cbb963ae554b1a767885ce48dde3ec58b6aaf (patch) | |
| tree | 30431562aca5b52c38666cba3bfa4c982d30f901 | |
| parent | edff783dee2060a8f49e13df47a101b15b4f547c (diff) | |
TextView implementation of select and delete gesture previews
Bug: 240436893
Test: atest android.widget.cts.TextViewHandwritingGestureTest
Change-Id: Ia4f02636b3bcaf2e2ac8a1baaa1c7b40c33d0dd6
| -rw-r--r-- | core/java/android/widget/TextView.java | 114 | ||||
| -rw-r--r-- | core/java/com/android/internal/inputmethod/EditableInputConnection.java | 9 |
2 files changed, 98 insertions, 25 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 7e7f9c99b948..b9b928e4c2f9 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -88,6 +88,7 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.os.CancellationSignal; import android.os.Handler; import android.os.LocaleList; import android.os.Parcel; @@ -149,6 +150,7 @@ import android.text.style.SuggestionSpan; import android.text.style.URLSpan; import android.text.style.UpdateAppearance; import android.text.util.Linkify; +import android.util.ArraySet; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.FeatureFlagUtils; @@ -200,6 +202,7 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InsertGesture; import android.view.inputmethod.JoinOrSplitGesture; +import android.view.inputmethod.PreviewableHandwritingGesture; import android.view.inputmethod.RemoveSpaceGesture; import android.view.inputmethod.SelectGesture; import android.view.inputmethod.SelectRangeGesture; @@ -244,6 +247,7 @@ import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Objects; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -9275,6 +9279,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener gestures.add(RemoveSpaceGesture.class); gestures.add(JoinOrSplitGesture.class); outAttrs.setSupportedHandwritingGestures(gestures); + + Set<Class<? extends PreviewableHandwritingGesture>> previews = new ArraySet<>(); + previews.add(SelectGesture.class); + previews.add(SelectRangeGesture.class); + previews.add(DeleteGesture.class); + previews.add(DeleteRangeGesture.class); + outAttrs.setSupportedHandwritingGesturePreviews(previews); + return ic; } } @@ -9486,83 +9498,130 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** @hide */ + public boolean previewHandwritingGesture( + @NonNull PreviewableHandwritingGesture gesture, + @Nullable CancellationSignal cancellationSignal) { + if (gesture instanceof SelectGesture) { + performHandwritingSelectGesture((SelectGesture) gesture, /* isPreview= */ true); + } else if (gesture instanceof SelectRangeGesture) { + performHandwritingSelectRangeGesture( + (SelectRangeGesture) gesture, /* isPreview= */ true); + } else if (gesture instanceof DeleteGesture) { + performHandwritingDeleteGesture((DeleteGesture) gesture, /* isPreview= */ true); + } else if (gesture instanceof DeleteRangeGesture) { + performHandwritingDeleteRangeGesture( + (DeleteRangeGesture) gesture, /* isPreview= */ true); + } else { + return false; + } + if (cancellationSignal != null) { + cancellationSignal.setOnCancelListener(this::clearGesturePreviewHighlight); + } + return true; + } + + /** @hide */ public int performHandwritingSelectGesture(@NonNull SelectGesture gesture) { + return performHandwritingSelectGesture(gesture, /* isPreview= */ false); + } + + private int performHandwritingSelectGesture(@NonNull SelectGesture gesture, boolean isPreview) { int[] range = getRangeForRect( convertFromScreenToContentCoordinates(gesture.getSelectionArea()), gesture.getGranularity()); if (range == null) { - return handleGestureFailure(gesture); + return handleGestureFailure(gesture, isPreview); + } + return performHandwritingSelectGesture(range, isPreview); + } + + private int performHandwritingSelectGesture(int[] range, boolean isPreview) { + if (isPreview) { + setSelectGesturePreviewHighlight(range[0], range[1]); + } else { + Selection.setSelection(getEditableText(), range[0], range[1]); + mEditor.startSelectionActionModeAsync(/* adjustSelection= */ false); } - Selection.setSelection(getEditableText(), range[0], range[1]); - mEditor.startSelectionActionModeAsync(/* adjustSelection= */ false); return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS; } /** @hide */ public int performHandwritingSelectRangeGesture(@NonNull SelectRangeGesture gesture) { + return performHandwritingSelectRangeGesture(gesture, /* isPreview= */ false); + } + + private int performHandwritingSelectRangeGesture( + @NonNull SelectRangeGesture gesture, boolean isPreview) { int[] startRange = getRangeForRect( convertFromScreenToContentCoordinates(gesture.getSelectionStartArea()), gesture.getGranularity()); if (startRange == null) { - return handleGestureFailure(gesture); + return handleGestureFailure(gesture, isPreview); } int[] endRange = getRangeForRect( convertFromScreenToContentCoordinates(gesture.getSelectionEndArea()), gesture.getGranularity()); if (endRange == null) { - return handleGestureFailure(gesture); + return handleGestureFailure(gesture, isPreview); } int[] range = new int[] { Math.min(startRange[0], endRange[0]), Math.max(startRange[1], endRange[1]) }; - Selection.setSelection(getEditableText(), range[0], range[1]); - mEditor.startSelectionActionModeAsync(/* adjustSelection= */ false); - return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS; + return performHandwritingSelectGesture(range, isPreview); } /** @hide */ public int performHandwritingDeleteGesture(@NonNull DeleteGesture gesture) { + return performHandwritingDeleteGesture(gesture, /* isPreview= */ false); + } + + private int performHandwritingDeleteGesture(@NonNull DeleteGesture gesture, boolean isPreview) { int[] range = getRangeForRect( convertFromScreenToContentCoordinates(gesture.getDeletionArea()), gesture.getGranularity()); if (range == null) { - return handleGestureFailure(gesture); + return handleGestureFailure(gesture, isPreview); } + return performHandwritingDeleteGesture(range, gesture.getGranularity(), isPreview); + } - if (gesture.getGranularity() == HandwritingGesture.GRANULARITY_WORD) { - range = adjustHandwritingDeleteGestureRange(range); - } + private int performHandwritingDeleteGesture(int[] range, int granularity, boolean isPreview) { + if (isPreview) { + setDeleteGesturePreviewHighlight(range[0], range[1]); + } else { + if (granularity == HandwritingGesture.GRANULARITY_WORD) { + range = adjustHandwritingDeleteGestureRange(range); + } - getEditableText().delete(range[0], range[1]); - Selection.setSelection(getEditableText(), range[0]); + getEditableText().delete(range[0], range[1]); + Selection.setSelection(getEditableText(), range[0]); + } return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS; } /** @hide */ public int performHandwritingDeleteRangeGesture(@NonNull DeleteRangeGesture gesture) { + return performHandwritingDeleteRangeGesture(gesture, /* isPreview= */ false); + } + + private int performHandwritingDeleteRangeGesture( + @NonNull DeleteRangeGesture gesture, boolean isPreview) { int[] startRange = getRangeForRect( convertFromScreenToContentCoordinates(gesture.getDeletionStartArea()), gesture.getGranularity()); if (startRange == null) { - return handleGestureFailure(gesture); + return handleGestureFailure(gesture, isPreview); } int[] endRange = getRangeForRect( convertFromScreenToContentCoordinates(gesture.getDeletionEndArea()), gesture.getGranularity()); if (endRange == null) { - return handleGestureFailure(gesture); + return handleGestureFailure(gesture, isPreview); } int[] range = new int[] { Math.min(startRange[0], endRange[0]), Math.max(startRange[1], endRange[1]) }; - - if (gesture.getGranularity() == HandwritingGesture.GRANULARITY_WORD) { - range = adjustHandwritingDeleteGestureRange(range); - } - - getEditableText().delete(range[0], range[1]); - Selection.setSelection(getEditableText(), range[0]); - return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS; + return performHandwritingDeleteGesture(range, gesture.getGranularity(), isPreview); } private int[] adjustHandwritingDeleteGestureRange(int[] range) { @@ -9740,7 +9799,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private int handleGestureFailure(HandwritingGesture gesture) { - if (!TextUtils.isEmpty(gesture.getFallbackText())) { + return handleGestureFailure(gesture, /* isPreview= */ false); + } + + private int handleGestureFailure(HandwritingGesture gesture, boolean isPreview) { + clearGesturePreviewHighlight(); + if (!isPreview && !TextUtils.isEmpty(gesture.getFallbackText())) { getEditableText() .replace(getSelectionStart(), getSelectionEnd(), gesture.getFallbackText()); return InputConnection.HANDWRITING_GESTURE_RESULT_FALLBACK; diff --git a/core/java/com/android/internal/inputmethod/EditableInputConnection.java b/core/java/com/android/internal/inputmethod/EditableInputConnection.java index 330ff8e61609..52e747150789 100644 --- a/core/java/com/android/internal/inputmethod/EditableInputConnection.java +++ b/core/java/com/android/internal/inputmethod/EditableInputConnection.java @@ -27,6 +27,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.RectF; import android.os.Bundle; +import android.os.CancellationSignal; import android.text.Editable; import android.text.Selection; import android.text.method.KeyListener; @@ -44,6 +45,7 @@ import android.view.inputmethod.HandwritingGesture; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InsertGesture; import android.view.inputmethod.JoinOrSplitGesture; +import android.view.inputmethod.PreviewableHandwritingGesture; import android.view.inputmethod.RemoveSpaceGesture; import android.view.inputmethod.SelectGesture; import android.view.inputmethod.SelectRangeGesture; @@ -321,6 +323,13 @@ public final class EditableInputConnection extends BaseInputConnection } @Override + public boolean previewHandwritingGesture( + @NonNull PreviewableHandwritingGesture gesture, + @Nullable CancellationSignal cancellationSignal) { + return mTextView.previewHandwritingGesture(gesture, cancellationSignal); + } + + @Override public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); CharSequence editableText = mTextView.getText(); |