Merge changes from topic "tr-anim" into sc-dev am: 27008c1123

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14661091

Change-Id: I09652536d90edf3c5f378159ccd89db6bca28909
This commit is contained in:
Ahaan Ugale
2021-05-28 02:11:10 +00:00
committed by Automerger Merge Worker
3 changed files with 104 additions and 8 deletions

View File

@@ -389,6 +389,14 @@ public class UiTranslationController {
continue;
}
mActivity.runOnUiThread(() -> {
if (view.getViewTranslationResponse() != null
&& view.getViewTranslationResponse().equals(response)) {
if (DEBUG) {
Log.d(TAG, "Duplicate ViewTranslationResponse for " + autofillId
+ ". Ignoring.");
}
return;
}
ViewTranslationCallback callback = view.getViewTranslationCallback();
if (callback == null) {
if (view instanceof TextView) {
@@ -396,9 +404,6 @@ public class UiTranslationController {
// implememtation.
callback = new TextViewTranslationCallback();
view.setViewTranslationCallback(callback);
if (mViewsToPadContent.contains(autofillId)) {
callback.enableContentPadding();
}
} else {
if (DEBUG) {
Log.d(TAG, view + " doesn't support showing translation because of "
@@ -407,6 +412,10 @@ public class UiTranslationController {
return;
}
}
callback.setAnimationDurationMillis(ANIMATION_DURATION_MILLIS);
if (mViewsToPadContent.contains(autofillId)) {
callback.enableContentPadding();
}
view.onViewTranslationResponse(response);
callback.onShowTranslation(view);
});
@@ -414,6 +423,9 @@ public class UiTranslationController {
}
}
// TODO: Use a device config value.
private static final int ANIMATION_DURATION_MILLIS = 250;
/**
* Creates a Translator for the given source and target translation specs and start the ui
* translation when the Translator is created successfully.

View File

@@ -64,4 +64,12 @@ public interface ViewTranslationCallback {
* @hide
*/
default void enableContentPadding() {}
/**
* Sets the duration for animations while transitioning the view between the original and
* translated contents.
*
* @hide
*/
default void setAnimationDurationMillis(int durationMillis) {}
}

View File

@@ -16,10 +16,15 @@
package android.widget;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.Build;
import android.text.TextUtils;
import android.text.method.TransformationMethod;
import android.text.method.TranslationTransformationMethod;
import android.util.Log;
import android.view.View;
@@ -47,6 +52,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
private boolean mIsShowingTranslation = false;
private boolean mIsTextPaddingEnabled = false;
private CharSequence mPaddedText;
private int mAnimationDurationMillis = 250; // default value
private CharSequence mContentDescription;
@@ -82,14 +88,19 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
*/
@Override
public boolean onShowTranslation(@NonNull View view) {
mIsShowingTranslation = true;
if (view.getViewTranslationResponse() == null) {
Log.wtf(TAG, "onShowTranslation() shouldn't be called before "
+ "onViewTranslationResponse().");
return false;
}
if (mTranslationTransformation != null) {
((TextView) view).setTransformationMethod(mTranslationTransformation);
final TransformationMethod transformation = mTranslationTransformation;
runWithAnimation(
(TextView) view,
() -> {
mIsShowingTranslation = true;
((TextView) view).setTransformationMethod(transformation);
});
ViewTranslationResponse response = view.getViewTranslationResponse();
if (response.getKeys().contains(ViewTranslationRequest.ID_CONTENT_DESCRIPTION)) {
CharSequence translatedContentDescription =
@@ -114,7 +125,6 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
*/
@Override
public boolean onHideTranslation(@NonNull View view) {
mIsShowingTranslation = false;
if (view.getViewTranslationResponse() == null) {
Log.wtf(TAG, "onHideTranslation() shouldn't be called before "
+ "onViewTranslationResponse().");
@@ -122,8 +132,14 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
}
// Restore to original text content.
if (mTranslationTransformation != null) {
((TextView) view).setTransformationMethod(
mTranslationTransformation.getOriginalTransformationMethod());
final TransformationMethod transformation =
mTranslationTransformation.getOriginalTransformationMethod();
runWithAnimation(
(TextView) view,
() -> {
mIsShowingTranslation = false;
((TextView) view).setTransformationMethod(transformation);
});
if (!TextUtils.isEmpty(mContentDescription)) {
view.setContentDescription(mContentDescription);
}
@@ -212,4 +228,64 @@ public class TextViewTranslationCallback implements ViewTranslationCallback {
}
private static final char COMPAT_PAD_CHARACTER = '\u2002';
@Override
public void setAnimationDurationMillis(int durationMillis) {
mAnimationDurationMillis = durationMillis;
}
/**
* Applies a simple text alpha animation when toggling between original and translated text. The
* text is fully faded out, then swapped to the new text, then the fading is reversed.
*
* @param runnable the operation to run on the view after the text is faded out, to change to
* displaying the original or translated text.
*/
private void runWithAnimation(TextView view, Runnable runnable) {
if (mAnimator != null) {
mAnimator.end();
// Note: mAnimator is now null; do not use again here.
}
int fadedOutColor = colorWithAlpha(view.getCurrentTextColor(), 0);
mAnimator = ValueAnimator.ofArgb(view.getCurrentTextColor(), fadedOutColor);
mAnimator.addUpdateListener(
// Note that if the text has a ColorStateList, this replaces it with a single color
// for all states. The original ColorStateList is restored when the animation ends
// (see below).
(valueAnimator) -> view.setTextColor((Integer) valueAnimator.getAnimatedValue()));
mAnimator.setRepeatMode(ValueAnimator.REVERSE);
mAnimator.setRepeatCount(1);
mAnimator.setDuration(mAnimationDurationMillis);
final ColorStateList originalColors = view.getTextColors();
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
view.setTextColor(originalColors);
mAnimator = null;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
runnable.run();
}
});
mAnimator.start();
}
private ValueAnimator mAnimator;
/**
* Returns {@code color} with alpha changed to {@code newAlpha}
*/
private static int colorWithAlpha(int color, int newAlpha) {
return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color));
}
}