From 4b01e37db52f5668e2d032e5016507d9a5c5dd08 Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Mon, 14 Nov 2022 09:54:49 +0100 Subject: [PATCH] Fix headsup notification RemoteInputView appearance animation This CL fixes a bug where the appearance animation of the RemoteInputView in a headsup collapsed notification was slightly broken. The RemoteInputView would do its appearance animation partly outside (below) the notification boundaries. This was because the RemoteInputView was prevented to overlap the hint during the expand animation. Bug: 174148361 Test: atest RemoteInputViewTest, Manual, i.e. posting various types of Notifications from the Notify2-RVC application with a reply action added to them. Then observing the animations visually and analyzing frames from screen recordings. Change-Id: I90a637e9b57dea0e365699cef9e088a562301f55 --- .../inflation/NotificationRowBinderImpl.java | 9 ++++++++- .../row/ExpandableNotificationRow.java | 11 ++++++++++- .../notification/row/NotificationContentView.java | 7 +++++++ .../statusbar/policy/RemoteInputView.java | 15 ++++++++++++++- .../statusbar/policy/RemoteInputViewTest.java | 5 +++++ 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java index 47cdde444dbda..56eb4b13dcde0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.inflation; +import static com.android.systemui.flags.Flags.NOTIFICATION_INLINE_REPLY_ANIMATION; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; @@ -30,6 +31,7 @@ import android.view.ViewGroup; import com.android.internal.util.NotificationMessagingUtil; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -71,6 +73,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { private NotificationListContainer mListContainer; private BindRowCallback mBindRowCallback; private NotificationClicker mNotificationClicker; + private FeatureFlags mFeatureFlags; @Inject public NotificationRowBinderImpl( @@ -82,7 +85,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { RowContentBindStage rowContentBindStage, Provider rowInflaterTaskProvider, ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder, - IconManager iconManager) { + IconManager iconManager, + FeatureFlags featureFlags) { mContext = context; mNotifBindPipeline = notifBindPipeline; mRowContentBindStage = rowContentBindStage; @@ -92,6 +96,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { mRowInflaterTaskProvider = rowInflaterTaskProvider; mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder; mIconManager = iconManager; + mFeatureFlags = featureFlags; } /** @@ -176,6 +181,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { entry.setRow(row); mNotifBindPipeline.manageRow(entry, row); mBindRowCallback.onBindRow(row); + row.setInlineReplyAnimationFlagEnabled( + mFeatureFlags.isEnabled(NOTIFICATION_INLINE_REPLY_ANIMATION)); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index c7c1634ea1055..c271f0990e88b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -284,6 +284,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private View.OnClickListener mOnAppClickListener; private View.OnClickListener mOnFeedbackClickListener; private Path mExpandingClipPath; + private boolean mIsInlineReplyAnimationFlagEnabled = false; // Listener will be called when receiving a long click event. // Use #setLongPressPosition to optionally assign positional data with the long press. @@ -3073,6 +3074,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return 0; } + public void setInlineReplyAnimationFlagEnabled(boolean isEnabled) { + mIsInlineReplyAnimationFlagEnabled = isEnabled; + } + @Override public void setActualHeight(int height, boolean notifyListeners) { boolean changed = height != getActualHeight(); @@ -3092,7 +3097,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } int contentHeight = Math.max(getMinHeight(), height); for (NotificationContentView l : mLayouts) { - l.setContentHeight(contentHeight); + if (mIsInlineReplyAnimationFlagEnabled) { + l.setContentHeight(height); + } else { + l.setContentHeight(contentHeight); + } } if (mIsSummaryWithChildren) { mChildrenContainer.setActualHeight(height); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 83d6abb4d9770..e46bf522acff6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -627,6 +627,13 @@ public class NotificationContentView extends FrameLayout implements Notification int hint; if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) { hint = getViewHeight(VISIBLE_TYPE_HEADSUP); + if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isAnimatingAppearance() + && mHeadsUpRemoteInputController.isFocusAnimationFlagActive()) { + // While the RemoteInputView is animating its appearance, it should be allowed + // to overlap the hint, therefore no space is reserved for the hint during the + // appearance animation of the RemoteInputView + hint = 0; + } } else if (mExpandedChild != null) { hint = getViewHeight(VISIBLE_TYPE_EXPANDED); } else if (mContractedChild != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index 9f5ad1c5fddcd..d8a8c5de90d70 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -143,6 +143,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene 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 @@ -418,6 +419,10 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene return true; } + public boolean isAnimatingAppearance() { + 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 @@ -624,8 +629,16 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); animator.start(); } else if (mIsFocusAnimationFlagActive && getVisibility() != VISIBLE) { + mIsAnimatingAppearance = true; setAlpha(0f); - getFocusAnimator(crossFadeView).start(); + Animator focusAnimator = getFocusAnimator(crossFadeView); + focusAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation, boolean isReverse) { + mIsAnimatingAppearance = false; + } + }); + focusAnimator.start(); } focus(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java index 1fe2008d2abea..2c472049cddaf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java @@ -21,7 +21,9 @@ import static com.android.systemui.statusbar.notification.stack.StackStateAnimat import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -392,12 +394,15 @@ public class RemoteInputViewTest extends SysuiTestCase { // Start focus animation view.focusAnimated(crossFadeView); + assertTrue(view.isAnimatingAppearance()); + // fast forward to end of animation mAnimatorTestRule.advanceTimeBy(ANIMATION_DURATION_STANDARD); // assert that crossFadeView's alpha is reset to 1f after the animation (hidden behind // RemoteInputView) assertEquals(1f, crossFadeView.getAlpha()); + assertFalse(view.isAnimatingAppearance()); assertEquals(View.VISIBLE, view.getVisibility()); assertEquals(1f, view.getAlpha()); }