diff options
| author | Ahaan Ugale <augale@google.com> | 2021-04-15 18:49:42 -0700 |
|---|---|---|
| committer | Ahaan Ugale <augale@google.com> | 2021-04-16 19:38:28 -0700 |
| commit | 71106418814942cf29940ea428ea4e5b0755be80 (patch) | |
| tree | 7da8c358aee84795de97155ad9930cd87495aeb9 /core/java/android/widget | |
| parent | 1198ed066befaaa96ce12e0479a92626ec3baf41 (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.java | 10 | ||||
| -rw-r--r-- | core/java/android/widget/TextViewTranslationCallback.java | 67 |
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'; } |
