Merge "Reapply changes of inline reply CL" into tm-qpr-dev

This commit is contained in:
Johannes Gallmann
2022-12-22 11:23:11 +00:00
committed by Android (Google) Code Review
3 changed files with 60 additions and 54 deletions

View File

@@ -464,9 +464,6 @@ public class NotificationRemoteInputManager implements Dumpable {
riv.getController().setRemoteInputs(inputs); riv.getController().setRemoteInputs(inputs);
riv.getController().setEditedSuggestionInfo(editedSuggestionInfo); riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
ViewGroup parent = view.getParent() != null ? (ViewGroup) view.getParent() : null; ViewGroup parent = view.getParent() != null ? (ViewGroup) view.getParent() : null;
if (parent != null) {
riv.setDefocusTargetHeight(parent.getHeight());
}
riv.focusAnimated(parent); riv.focusAnimated(parent);
if (userMessageContent != null) { if (userMessageContent != null) {
riv.setEditTextContent(userMessageContent); riv.setEditTextContent(userMessageContent);

View File

@@ -47,6 +47,7 @@ import android.view.OnReceiveContentListener;
import android.view.View; import android.view.View;
import android.view.ViewAnimationUtils; import android.view.ViewAnimationUtils;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewGroupOverlay;
import android.view.ViewRootImpl; import android.view.ViewRootImpl;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.view.WindowInsetsAnimation; import android.view.WindowInsetsAnimation;
@@ -57,7 +58,6 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.EditText; import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@@ -133,6 +133,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
private RevealParams mRevealParams; private RevealParams mRevealParams;
private Rect mContentBackgroundBounds; private Rect mContentBackgroundBounds;
private boolean mIsFocusAnimationFlagActive; private boolean mIsFocusAnimationFlagActive;
private boolean mIsAnimatingAppearance = false;
// TODO(b/193539698): move these to a Controller // TODO(b/193539698): move these to a Controller
private RemoteInputController mController; private RemoteInputController mController;
@@ -142,10 +143,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
private boolean mSending; private boolean mSending;
private NotificationViewWrapper mWrapper; private NotificationViewWrapper mWrapper;
private Integer mDefocusTargetHeight = null;
private boolean mIsAnimatingAppearance = false;
// TODO(b/193539698): remove this; views shouldn't have access to their controller, and places // TODO(b/193539698): remove this; views shouldn't have access to their controller, and places
// that need the controller shouldn't have access to the view // that need the controller shouldn't have access to the view
private RemoteInputViewController mViewController; private RemoteInputViewController mViewController;
@@ -423,18 +420,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
return mIsAnimatingAppearance; return mIsAnimatingAppearance;
} }
/**
* View will ensure to use at most the provided defocusTargetHeight, when defocusing animated.
* This is to ensure that the parent can resize itself to the targetHeight while the defocus
* animation of the RemoteInputView is running.
*
* @param defocusTargetHeight The target height the parent will resize itself to. If null, the
* RemoteInputView will not resize itself.
*/
public void setDefocusTargetHeight(Integer defocusTargetHeight) {
mDefocusTargetHeight = defocusTargetHeight;
}
@VisibleForTesting @VisibleForTesting
void onDefocus(boolean animate, boolean logClose) { void onDefocus(boolean animate, boolean logClose) {
mController.removeRemoteInput(mEntry, mToken); mController.removeRemoteInput(mEntry, mToken);
@@ -443,35 +428,28 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
// During removal, we get reattached and lose focus. Not hiding in that // During removal, we get reattached and lose focus. Not hiding in that
// case to prevent flicker. // case to prevent flicker.
if (!mRemoved) { if (!mRemoved) {
if (animate && mIsFocusAnimationFlagActive) { ViewGroup parent = (ViewGroup) getParent();
Animator animator = getDefocusAnimator(); if (animate && parent != null && mIsFocusAnimationFlagActive) {
// When defocusing, the notification needs to shrink. Therefore, we need to free
// up the space that is needed for the RemoteInputView. This is done by setting
// a negative top margin of the height difference of the RemoteInputView and its
// sibling (the actions_container_layout containing the Reply button)
if (mDefocusTargetHeight != null && mDefocusTargetHeight < getHeight()
&& mDefocusTargetHeight >= 0
&& getLayoutParams() instanceof FrameLayout.LayoutParams) {
int heightToShrink = getHeight() - mDefocusTargetHeight;
FrameLayout.LayoutParams layoutParams =
(FrameLayout.LayoutParams) getLayoutParams();
layoutParams.topMargin = -heightToShrink;
setLayoutParams(layoutParams);
((ViewGroup) getParent().getParent()).setClipChildren(false);
}
ViewGroup grandParent = (ViewGroup) parent.getParent();
ViewGroupOverlay overlay = parent.getOverlay();
// After adding this RemoteInputView to the overlay of the parent (and thus removing
// it from the parent itself), the parent will shrink in height. This causes the
// overlay to be moved. To correct the position of the overlay we need to offset it.
int overlayOffsetY = getMaxSiblingHeight() - getHeight();
overlay.add(this);
if (grandParent != null) grandParent.setClipChildren(false);
Animator animator = getDefocusAnimator(overlayOffsetY);
View self = this;
animator.addListener(new AnimatorListenerAdapter() { animator.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
//reset top margin after the animation overlay.remove(self);
if (getLayoutParams() instanceof FrameLayout.LayoutParams) { parent.addView(self);
FrameLayout.LayoutParams layoutParams = if (grandParent != null) grandParent.setClipChildren(true);
(FrameLayout.LayoutParams) getLayoutParams();
layoutParams.topMargin = 0;
setLayoutParams(layoutParams);
((ViewGroup) getParent().getParent()).setClipChildren(true);
}
setVisibility(GONE); setVisibility(GONE);
if (mWrapper != null) { if (mWrapper != null) {
mWrapper.setRemoteInputVisible(false); mWrapper.setRemoteInputVisible(false);
@@ -609,7 +587,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
} }
/** /**
* Sets whether the feature flag for the updated inline reply animation is active or not. * Sets whether the feature flag for the revised inline reply animation is active or not.
* @param active * @param active
*/ */
public void setIsFocusAnimationFlagActive(boolean active) { public void setIsFocusAnimationFlagActive(boolean active) {
@@ -846,6 +824,23 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
} }
} }
/**
* @return max sibling height (0 in case of no siblings)
*/
public int getMaxSiblingHeight() {
ViewGroup parentView = (ViewGroup) getParent();
int maxHeight = 0;
if (parentView == null) return 0;
for (int i = 0; i < parentView.getChildCount(); i++) {
View siblingView = parentView.getChildAt(i);
if (siblingView != this) maxHeight = Math.max(maxHeight, siblingView.getHeight());
}
return maxHeight;
}
/**
* Creates an animator for the focus animation.
*/
private Animator getFocusAnimator(View crossFadeView) { private Animator getFocusAnimator(View crossFadeView) {
final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 0f, 1f); final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 0f, 1f);
alphaAnimator.setStartDelay(FOCUS_ANIMATION_FADE_IN_DELAY); alphaAnimator.setStartDelay(FOCUS_ANIMATION_FADE_IN_DELAY);
@@ -854,7 +849,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
ValueAnimator scaleAnimator = ValueAnimator.ofFloat(FOCUS_ANIMATION_MIN_SCALE, 1f); ValueAnimator scaleAnimator = ValueAnimator.ofFloat(FOCUS_ANIMATION_MIN_SCALE, 1f);
scaleAnimator.addUpdateListener(valueAnimator -> { scaleAnimator.addUpdateListener(valueAnimator -> {
setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue()); setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue(), 0);
}); });
scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION); scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN); scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
@@ -875,21 +870,26 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
return animatorSet; return animatorSet;
} }
private Animator getDefocusAnimator() { /**
* Creates an animator for the defocus animation.
*
* @param offsetY The RemoteInputView will be offset by offsetY during the animation
*/
private Animator getDefocusAnimator(int offsetY) {
final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f); final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f);
alphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION); alphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION);
alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR); alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
ValueAnimator scaleAnimator = ValueAnimator.ofFloat(1f, FOCUS_ANIMATION_MIN_SCALE); ValueAnimator scaleAnimator = ValueAnimator.ofFloat(1f, FOCUS_ANIMATION_MIN_SCALE);
scaleAnimator.addUpdateListener(valueAnimator -> { scaleAnimator.addUpdateListener(valueAnimator -> {
setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue()); setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue(), offsetY);
}); });
scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION); scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN); scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
scaleAnimator.addListener(new AnimatorListenerAdapter() { scaleAnimator.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation, boolean isReverse) { public void onAnimationEnd(Animator animation, boolean isReverse) {
setFocusAnimationScaleY(1f); setFocusAnimationScaleY(1f /* scaleY */, 0 /* verticalOffset */);
} }
}); });
@@ -901,15 +901,21 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
/** /**
* Sets affected view properties for a vertical scale animation * Sets affected view properties for a vertical scale animation
* *
* @param scaleY desired vertical view scale * @param scaleY desired vertical view scale
* @param verticalOffset vertical offset to apply to the RemoteInputView during the animation
*/ */
private void setFocusAnimationScaleY(float scaleY) { private void setFocusAnimationScaleY(float scaleY, int verticalOffset) {
int verticalBoundOffset = (int) ((1f - scaleY) * 0.5f * mContentView.getHeight()); int verticalBoundOffset = (int) ((1f - scaleY) * 0.5f * mContentView.getHeight());
mContentBackgroundBounds = new Rect(0, verticalBoundOffset, mContentView.getWidth(), Rect contentBackgroundBounds = new Rect(0, verticalBoundOffset, mContentView.getWidth(),
mContentView.getHeight() - verticalBoundOffset); mContentView.getHeight() - verticalBoundOffset);
mContentBackground.setBounds(mContentBackgroundBounds); mContentBackground.setBounds(contentBackgroundBounds);
mContentView.setBackground(mContentBackground); mContentView.setBackground(mContentBackground);
setTranslationY(verticalBoundOffset); if (scaleY == 1f) {
mContentBackgroundBounds = null;
} else {
mContentBackgroundBounds = contentBackgroundBounds;
}
setTranslationY(verticalBoundOffset + verticalOffset);
} }
/** Handler for button click on send action in IME. */ /** Handler for button click on send action in IME. */

View File

@@ -55,6 +55,7 @@ import android.view.ViewRootImpl;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.widget.EditText; import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher; import android.window.OnBackInvokedDispatcher;
@@ -414,7 +415,9 @@ public class RemoteInputViewTest extends SysuiTestCase {
mDependency, mDependency,
TestableLooper.get(this)); TestableLooper.get(this));
ExpandableNotificationRow row = helper.createRow(); ExpandableNotificationRow row = helper.createRow();
FrameLayout remoteInputViewParent = new FrameLayout(mContext);
RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController); RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
remoteInputViewParent.addView(view);
bindController(view, row.getEntry()); bindController(view, row.getEntry());
// Start defocus animation // Start defocus animation