summaryrefslogtreecommitdiff
path: root/core/java/android/widget/TextView.java
diff options
context:
space:
mode:
authorJoanne Chung <joannechung@google.com>2020-12-30 00:05:02 +0800
committerJoanne Chung <joannechung@google.com>2021-01-25 18:57:14 +0800
commita5fa9bc0f7d861b9a083aab3a43b60da1e19b9af (patch)
tree186c1a440f880d71d91146fbb6c3a54397072faf /core/java/android/widget/TextView.java
parentd9e22f9ac96610cb2b4780c1615a2b262abe7d63 (diff)
Add initial View's APIs for auto translation
The initial APIs for auto translation flow. The implementation of sending request and dealing spans will on the follow up changes. Bug: 172969740 Test: manual build pass. Use a sample app to call api get expected result. Change-Id: Ief45190026e6205ff18366c1aaba8f424a4df00c
Diffstat (limited to 'core/java/android/widget/TextView.java')
-rw-r--r--core/java/android/widget/TextView.java120
1 files changed, 120 insertions, 0 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b8660255acc1..8cfbca88c596 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -129,6 +129,7 @@ import android.text.method.TextKeyListener;
import android.text.method.TimeKeyListener;
import android.text.method.TransformationMethod;
import android.text.method.TransformationMethod2;
+import android.text.method.TranslationTransformationMethod;
import android.text.method.WordIterator;
import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
@@ -193,6 +194,7 @@ import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;
import android.view.textservice.SpellCheckerSubtype;
import android.view.textservice.TextServicesManager;
+import android.view.translation.TranslationRequest;
import android.widget.RemoteViews.RemoteView;
import com.android.internal.annotations.VisibleForTesting;
@@ -732,6 +734,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private MovementMethod mMovement;
private TransformationMethod mTransformation;
+ private TranslationTransformationMethod mTranslationTransformation;
@UnsupportedAppUsage
private boolean mAllowTransformationLengthChange;
@UnsupportedAppUsage
@@ -13814,4 +13817,121 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Log.d(LOG_TAG, location + ": " + String.format(msgFormat, msgArgs));
}
}
+
+ /**
+ * Provides a {@link TranslationRequest} that represents the content to be translated via
+ * translation service.
+ *
+ * <p>NOTE: When overriding the method, it should not translate the password. We also suggest
+ * that not translating the text is selectable or editable. We use the transformation method to
+ * implement showing the translated text. The TextView does not support the transformation
+ * method text length change. If the text is selectable or editable, it will crash while
+ * selecting the text. To support it, it needs broader changes to text APIs, we only allow to
+ * translate non selectable and editable text now.
+ *
+ * @hide
+ */
+ @Nullable
+ @Override
+ public TranslationRequest onCreateTranslationRequest() {
+ if (mText == null || mText.length() == 0) {
+ return null;
+ }
+ // Not translate password, editable text and not important for translation
+ // TODO(b/177214256): support selectable text translation. It needs to broader changes to
+ // text selection apis, not support in S.
+ boolean isPassword = isAnyPasswordInputType() || hasPasswordTransformationMethod();
+ if (isTextEditable() || isPassword || isTextSelectable()) {
+ return null;
+ }
+ // TODO(b/176488462): apply the view's important for translation property
+ // TODO(b/174283799): remove the spans from the mText and save the spans informatopn
+ TranslationRequest request =
+ new TranslationRequest.Builder()
+ .setAutofillId(getAutofillId())
+ .setTranslationText(mText)
+ .build();
+ return request;
+ }
+
+ /**
+ * Provides the implementation that pauses the ongoing Ui translation, it will show the original
+ * text instead of the translated text and restore the original transformation method.
+ *
+ * <p>NOTE: If this method is overridden, other translation related methods such as
+ * {@link onRestoreUiTranslation}, {@link onFinishUiTranslation}, {@link onTranslationComplete}
+ * should also be overridden.
+ *
+ * @hide
+ */
+ @Override
+ public void onPauseUiTranslation() {
+ // Restore to original text content.
+ if (mTranslationTransformation != null) {
+ setTransformationMethod(mTranslationTransformation.getOriginalTransformationMethod());
+ }
+ }
+
+ /**
+ * Provides the implementation that restoes the paused Ui translation, it will show the
+ * translated text again if the text had been translated. This method will replace the current
+ * tansformation method with {@link TranslationTransformationMethod}.
+ *
+ * <p>NOTE: If this method is overridden, other translation related methods such as
+ * {@link onPauseUiTranslation}, {@link onFinishUiTranslation}, {@link onTranslationComplete}
+ * should also be overridden.
+ *
+ * @hide
+ */
+ @Override
+ public void onRestoreUiTranslation() {
+ if (mTranslationTransformation != null) {
+ setTransformationMethod(mTranslationTransformation);
+ } else {
+ Log.w(LOG_TAG, "onResumeTranslatedText(): no translated text.");
+ }
+ }
+
+ /**
+ * Provides the implementation that finishes the current Ui translation and it's no longer to
+ * show the translated text. This method restores the original transformation method and resets
+ * the saved {@link TranslationTransformationMethod}.
+ *
+ * <p>NOTE: If this method is overridden, other translation related methods such as
+ * {@link onPauseUiTranslation}, {@link onRestoreUiTranslation}, {@link onTranslationComplete}
+ * should also be overridden.
+ *
+ * @hide
+ */
+ @Override
+ public void onFinishUiTranslation() {
+ // Restore to original text content and clear TranslationTransformation
+ if (mTranslationTransformation != null) {
+ setTransformationMethod(mTranslationTransformation.getOriginalTransformationMethod());
+ mTranslationTransformation = null;
+ }
+ }
+
+ /**
+ * Default {@link TextView} implementation after the translation request is done by the
+ * translation service, it's ok to show the translated text. This method will save the original
+ * transformation method and replace the current transformation method with
+ * {@link TranslationTransformationMethod}.
+ *
+ * <p>NOTE: If this method is overridden, other translation related methods such as
+ * {@link onPauseUiTranslation}, {@link onRestoreUiTranslation}, {@link onFinishUiTranslation}
+ * should also be overridden.
+ *
+ * @hide
+ */
+ @Override
+ public void onTranslationComplete(@NonNull TranslationRequest data) {
+ // Show the translated text.
+ TransformationMethod originalTranslationMethod = mTranslationTransformation != null
+ ? mTranslationTransformation.getOriginalTransformationMethod() : mTransformation;
+ mTranslationTransformation =
+ new TranslationTransformationMethod(data, originalTranslationMethod);
+ // TODO(b/178353965): well-handle setTransformationMethod.
+ setTransformationMethod(mTranslationTransformation);
+ }
}