Merge "AutoTranslate: Pad view text for compatibility reasons." into sc-dev
This commit is contained in:
@@ -78,24 +78,11 @@ public class TranslationTransformationMethod implements TransformationMethod2 {
|
||||
if (TextUtils.isEmpty(translatedText) || isWhitespace(translatedText.toString())) {
|
||||
return source;
|
||||
} else {
|
||||
// TODO(b/179693024): Remove this once we have the fix to pad the view text instead.
|
||||
translatedText = ellipsize(translatedText, ((TextView) view).getText().length());
|
||||
// TODO(b/174283799): apply the spans to the text
|
||||
return translatedText;
|
||||
}
|
||||
}
|
||||
|
||||
private static CharSequence ellipsize(CharSequence text, int newLength) {
|
||||
if (text.length() <= newLength) {
|
||||
return text;
|
||||
}
|
||||
String ellipsis = String.valueOf('\u2026');
|
||||
if (newLength == 1) {
|
||||
return ellipsis;
|
||||
}
|
||||
return TextUtils.concat(TextUtils.trimToSize(text, newLength - 1), ellipsis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusChanged(View view, CharSequence sourceText,
|
||||
boolean focused, int direction,
|
||||
|
||||
@@ -362,17 +362,20 @@ public class UiTranslationController {
|
||||
continue;
|
||||
}
|
||||
mActivity.runOnUiThread(() -> {
|
||||
if (view.getViewTranslationCallback() == null) {
|
||||
final ViewTranslationCallback callback = view.getViewTranslationCallback();
|
||||
if (callback == null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, view + " doesn't support showing translation because of "
|
||||
+ "null ViewTranslationCallback.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Do this for specific views on request only.
|
||||
callback.enableContentPadding();
|
||||
|
||||
view.onTranslationResponse(response);
|
||||
if (view.getViewTranslationCallback() != null) {
|
||||
view.getViewTranslationCallback().onShowTranslation(view);
|
||||
}
|
||||
callback.onShowTranslation(view);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,4 +48,16 @@ public interface ViewTranslationCallback {
|
||||
* @return {@code true} if the View handles clearing the translation.
|
||||
*/
|
||||
boolean onClearTranslation(@NonNull View view);
|
||||
|
||||
/**
|
||||
* Enables padding on the view's original content.
|
||||
* <p>
|
||||
* This is useful when we do not modify the content directly, rather use a mechanism like
|
||||
* {@link android.text.method.TransformationMethod}. If the app misbehaves when the displayed
|
||||
* translation and the underlying content have different sizes, the platform intelligence can
|
||||
* request that the original content be padded to make the sizes match.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
default void enableContentPadding() {}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user