summaryrefslogtreecommitdiff
path: root/core/java/android/widget
diff options
context:
space:
mode:
authorAhaan Ugale <augale@google.com>2021-04-15 18:49:42 -0700
committerAhaan Ugale <augale@google.com>2021-04-16 19:38:28 -0700
commit71106418814942cf29940ea428ea4e5b0755be80 (patch)
tree7da8c358aee84795de97155ad9930cd87495aeb9 /core/java/android/widget
parent1198ed066befaaa96ce12e0479a92626ec3baf41 (diff)
AutoTranslate: Pad view text for compatibility reasons.
Some apps operate on the view text based on layout calculations made on the transformed text. This can cause issues (even crashes) if the transformed text is longer than the original, as is often the case with Translate. A previous temporary fix, I685ae4a9752c817db81f0d736f1d746b2e4a9839, ellipsized the translated text. This change fixes it properly by instead padding the original text. A followup change will make this controllable by API instead of padding every TextView. The en space character, U+2002, is used for the padding here. It seems to work well in practice for multiple languages. We don't make this configurable through API as it could make debugging harder (issues triggered by server-side changes). Bug: 179693024 Test: atest CtsTranslationTestCases Test: manual - toggling between original and translated, scrolling, new views appearing, multiple apps Change-Id: I9d7db5d2bc200e4042baf3267796f00cfc298f19
Diffstat (limited to 'core/java/android/widget')
-rw-r--r--core/java/android/widget/TextView.java10
-rw-r--r--core/java/android/widget/TextViewTranslationCallback.java67
2 files changed, 74 insertions, 3 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 40c79cf086fc..1953a7687cb9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -770,6 +770,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private final boolean mUseInternationalizedInput;
// True if fallback fonts that end up getting used should be allowed to affect line spacing.
/* package */ boolean mUseFallbackLineSpacing;
+ // True if the view text can be padded for compat reasons, when the view is translated.
+ private final boolean mUseTextPaddingForUiTranslation;
@ViewDebug.ExportedProperty(category = "text")
@UnsupportedAppUsage
@@ -1480,6 +1482,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
mUseInternationalizedInput = targetSdkVersion >= VERSION_CODES.O;
mUseFallbackLineSpacing = targetSdkVersion >= VERSION_CODES.P;
+ // TODO(b/179693024): Use a ChangeId instead.
+ mUseTextPaddingForUiTranslation = targetSdkVersion <= Build.VERSION_CODES.R;
if (inputMethod != null) {
Class<?> c;
@@ -2372,6 +2376,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@ViewDebug.CapturedViewProperty
@InspectableProperty
public CharSequence getText() {
+ if (mUseTextPaddingForUiTranslation
+ && mDefaultTranslationCallback != null
+ && mDefaultTranslationCallback.isTextPaddingEnabled()
+ && mDefaultTranslationCallback.isShowingTranslation()) {
+ return mDefaultTranslationCallback.getPaddedText(mText, mTransformed);
+ }
return mText;
}
diff --git a/core/java/android/widget/TextViewTranslationCallback.java b/core/java/android/widget/TextViewTranslationCallback.java
index a479b8ac4760..73f19a7a48c0 100644
--- a/core/java/android/widget/TextViewTranslationCallback.java
+++ b/core/java/android/widget/TextViewTranslationCallback.java
@@ -17,6 +17,7 @@
package android.widget;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.os.Build;
import android.text.method.TranslationTransformationMethod;
import android.util.Log;
@@ -33,7 +34,7 @@ import android.view.translation.ViewTranslationResponse;
*/
public class TextViewTranslationCallback implements ViewTranslationCallback {
- private static final String TAG = "TextViewTranslationCallback";
+ private static final String TAG = "TextViewTranslationCb";
// TODO(b/182433547): remove Build.IS_DEBUGGABLE before ship. Enable the logging in debug build
// to help the debug during the development phase
@@ -41,6 +42,9 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
|| Build.IS_DEBUGGABLE;
private TranslationTransformationMethod mTranslationTransformation;
+ private boolean mIsShowingTranslation = false;
+ private boolean mIsTextPaddingEnabled = false;
+ private CharSequence mPaddedText;
/**
* Invoked by the platform when receiving the successful {@link ViewTranslationResponse} for the
@@ -74,6 +78,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
*/
@Override
public boolean onShowTranslation(@NonNull View view) {
+ mIsShowingTranslation = true;
if (mTranslationTransformation != null) {
((TextView) view).setTransformationMethod(mTranslationTransformation);
} else {
@@ -90,6 +95,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
*/
@Override
public boolean onHideTranslation(@NonNull View view) {
+ mIsShowingTranslation = false;
// Restore to original text content.
if (mTranslationTransformation != null) {
((TextView) view).setTransformationMethod(
@@ -110,9 +116,9 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
public boolean onClearTranslation(@NonNull View view) {
// Restore to original text content and clear TranslationTransformation
if (mTranslationTransformation != null) {
- ((TextView) view).setTransformationMethod(
- mTranslationTransformation.getOriginalTransformationMethod());
+ onHideTranslation(view);
clearTranslationTransformation();
+ mPaddedText = null;
} else {
if (DEBUG) {
// TODO(b/182433547): remove before S release
@@ -121,4 +127,59 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
}
return true;
}
+
+ boolean isShowingTranslation() {
+ return mIsShowingTranslation;
+ }
+
+ @Override
+ public void enableContentPadding() {
+ mIsTextPaddingEnabled = true;
+ }
+
+ /**
+ * Returns whether readers of the view text should receive padded text for compatibility
+ * reasons. The view's original text will be padded to match the length of the translated text.
+ */
+ boolean isTextPaddingEnabled() {
+ return mIsTextPaddingEnabled;
+ }
+
+ /**
+ * Returns the view's original text with padding added. If the translated text isn't longer than
+ * the original text, returns the original text itself.
+ *
+ * @param text the view's original text
+ * @param translatedText the view's translated text
+ * @see #isTextPaddingEnabled()
+ */
+ @Nullable
+ CharSequence getPaddedText(CharSequence text, CharSequence translatedText) {
+ if (text == null) {
+ return null;
+ }
+ if (mPaddedText == null) {
+ mPaddedText = computePaddedText(text, translatedText);
+ }
+ return mPaddedText;
+ }
+
+ @NonNull
+ private CharSequence computePaddedText(CharSequence text, CharSequence translatedText) {
+ if (translatedText == null) {
+ return text;
+ }
+ int newLength = translatedText.length();
+ if (newLength <= text.length()) {
+ return text;
+ }
+ StringBuilder sb = new StringBuilder(newLength);
+ sb.append(text);
+ for (int i = text.length(); i < newLength; i++) {
+ sb.append(COMPAT_PAD_CHARACTER);
+ }
+ return sb;
+ }
+
+ private static final char COMPAT_PAD_CHARACTER = '\u2002';
}