Merge "Refine the ViewTranslationCallback usage." into sc-dev

This commit is contained in:
Joanne Chung
2021-05-22 07:41:18 +00:00
committed by Android (Google) Code Review
3 changed files with 84 additions and 56 deletions

View File

@@ -3514,6 +3514,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* 11 PFLAG4_SCROLL_CAPTURE_HINT_MASK
* 1 PFLAG4_ALLOW_CLICK_WHEN_DISABLED
* 1 PFLAG4_DETACHED
* 1 PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
* |-------|-------|-------|-------|
*/
@@ -3580,6 +3581,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private static final int PFLAG4_DETACHED = 0x000002000;
/**
* Indicates that the view has transient state because the system is translating it.
*/
private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000;
/* End of masks for mPrivateFlags4 */
/** @hide */
@@ -12270,6 +12276,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
/**
* Set the view is tracking translation transient state. This flag is used to check if the view
* need to call setHasTransientState(false) to reset transient state that set when starting
* translation.
*
* @param hasTranslationTransientState true if this view has translation transient state
* @hide
*/
public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
if (hasTranslationTransientState) {
mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
} else {
mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
}
}
/**
* @hide
*/
public boolean hasTranslationTransientState() {
return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE)
== PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
}
/**
* Returns true if this view is currently attached to a window.
*/
@@ -30839,6 +30869,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
* Returns a {@link ViewTranslationCallback} that is used to display the translated information
* or {@code null} if this View doesn't support translation.
*
* @hide
*/
@Nullable
@@ -30925,7 +30958,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual
* children to build {@link ViewTranslationRequest} if the view should be translated.
* The view is marked as having {@link #setHasTransientState(boolean) transient state} so that
* recycling of views doesn't prevent the system from attaching the response to it.</p>
* recycling of views doesn't prevent the system from attaching the response to it. Therefore,
* if overriding this method, you should set or reset the transient state. </p>
*
* @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or
* {@code null} if the view doesn't have virtual child that should be translated. The virtual
@@ -30975,10 +31009,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for "
+ getAutofillId());
}
// TODO: Add a default ViewTranslationCallback for View that resets this in
// onClearTranslation(). Also update the javadoc for this method to mention
// that.
setHasTransientState(true);
setHasTranslationTransientState(true);
}
}
}

View File

@@ -43,6 +43,8 @@ import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
import android.view.autofill.AutofillId;
import android.view.translation.UiTranslationManager.UiTranslationState;
import android.widget.TextView;
import android.widget.TextViewTranslationCallback;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -146,7 +148,13 @@ public class UiTranslationController {
break;
case STATE_UI_TRANSLATION_FINISHED:
destroyTranslators();
runForEachView((view, callback) -> callback.onClearTranslation(view));
runForEachView((view, callback) -> {
callback.onClearTranslation(view);
if (view.hasTranslationTransientState()) {
view.setHasTransientState(false);
view.setHasTranslationTransientState(false);
}
});
synchronized (mLock) {
mViews.clear();
}
@@ -381,17 +389,23 @@ public class UiTranslationController {
continue;
}
mActivity.runOnUiThread(() -> {
final ViewTranslationCallback callback = view.getViewTranslationCallback();
ViewTranslationCallback callback = view.getViewTranslationCallback();
if (callback == null) {
if (DEBUG) {
Log.d(TAG, view + " doesn't support showing translation because of "
+ "null ViewTranslationCallback.");
if (view instanceof TextView) {
// developer doesn't provide their override, we set the default TextView
// 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 "
+ "null ViewTranslationCallback.");
}
return;
}
return;
}
if (mViewsToPadContent.contains(autofillId)) {
callback.enableContentPadding();
}
view.onViewTranslationResponse(response);
callback.onShowTranslation(view);

View File

@@ -740,7 +740,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private MovementMethod mMovement;
private TransformationMethod mTransformation;
private TextViewTranslationCallback mDefaultTranslationCallback;
@UnsupportedAppUsage
private boolean mAllowTransformationLengthChange;
@UnsupportedAppUsage
@@ -2376,11 +2375,16 @@ 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);
if (mUseTextPaddingForUiTranslation) {
ViewTranslationCallback callback = getViewTranslationCallback();
if (callback != null && callback instanceof TextViewTranslationCallback) {
TextViewTranslationCallback defaultCallback =
(TextViewTranslationCallback) callback;
if (defaultCallback.isTextPaddingEnabled()
&& defaultCallback.isShowingTranslation()) {
return defaultCallback.getPaddedText(mText, mTransformed);
}
}
}
return mText;
}
@@ -13932,30 +13936,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
requestsCollector.accept(requestBuilder.build());
}
/**
* Returns a {@link ViewTranslationCallback} that is used to display the translated information.
* The default implementation will use a {@link TransformationMethod} that allow to replace the
* current {@link TransformationMethod} to transform the original text to the translated text
* display.
*
* @return a {@link ViewTranslationCallback} that is used to control how to display the
* translated information or {@code null} if this View doesn't support translation.
*
* @hide
*/
@Nullable
@Override
public ViewTranslationCallback getViewTranslationCallback() {
return getDefaultViewTranslationCallback();
}
private ViewTranslationCallback getDefaultViewTranslationCallback() {
if (mDefaultTranslationCallback == null) {
mDefaultTranslationCallback = new TextViewTranslationCallback();
}
return mDefaultTranslationCallback;
}
/**
*
* Called when the content from {@link #onCreateViewTranslationRequest} had been translated by
@@ -13969,17 +13949,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
// set ViewTranslationResponse
super.onViewTranslationResponse(response);
// TODO(b/183467275): Use the overridden ViewTranslationCallback instead of our default
// implementation if the view has overridden getViewTranslationCallback.
TextViewTranslationCallback callback =
(TextViewTranslationCallback) getDefaultViewTranslationCallback();
TranslationTransformationMethod oldTranslationMethod =
callback.getTranslationTransformation();
TransformationMethod originalTranslationMethod = oldTranslationMethod != null
? oldTranslationMethod.getOriginalTransformationMethod() : mTransformation;
TranslationTransformationMethod newTranslationMethod =
new TranslationTransformationMethod(response, originalTranslationMethod);
// TODO(b/178353965): well-handle setTransformationMethod.
callback.setTranslationTransformation(newTranslationMethod);
// TODO(b/178353965): move to ViewTranslationCallback.onShow()
ViewTranslationCallback callback = getViewTranslationCallback();
if (callback instanceof TextViewTranslationCallback) {
TextViewTranslationCallback textViewDefaultCallback =
(TextViewTranslationCallback) callback;
TranslationTransformationMethod oldTranslationMethod =
textViewDefaultCallback.getTranslationTransformation();
TransformationMethod originalTranslationMethod = oldTranslationMethod != null
? oldTranslationMethod.getOriginalTransformationMethod() : mTransformation;
TranslationTransformationMethod newTranslationMethod =
new TranslationTransformationMethod(response, originalTranslationMethod);
// TODO(b/178353965): well-handle setTransformationMethod.
textViewDefaultCallback.setTranslationTransformation(newTranslationMethod);
}
}
}