Don't collapse the Shade when expanding a notification.
This CL prevents the Shade from collapsing if a notification expansion animation is pending/running. It does so by: 1. Making sure that StatusBarNotificationActivityStarter#shouldCollapse is checked *after* ActivityLaunchAnimator#setLaunchResult is called. 2. Updating the clipped area of the parent of the notification that is expanding, if any. 3. Not moving the QS or the notification siblings while the animation is running. 4. Making sure that the notification is displayed above the QS. See b/181654098#comment4 for before/after videos. Bug: 181654098 Test: Manual; atest ActivityLaunchAnimatorTest ExpandableNotificationRowTest NotificationChildrenContainerTest NotificationStackScrollLayoutTest StatusBarNotificationActivityStarterTest Change-Id: I5a7beb4dc4883ed2757e286c4b480f83709680f7
This commit is contained in:
@@ -2027,17 +2027,22 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
int top = params.getTop();
|
||||
float interpolation = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(params.getProgress());
|
||||
int startClipTopAmount = params.getStartClipTopAmount();
|
||||
int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, interpolation);
|
||||
if (mNotificationParent != null) {
|
||||
float parentY = mNotificationParent.getTranslationY();
|
||||
top -= parentY;
|
||||
mNotificationParent.setTranslationZ(translationZ);
|
||||
|
||||
// When the expanding notification is below its parent, the parent must be clipped
|
||||
// exactly how it was clipped before the animation. When the expanding notification is
|
||||
// on or above its parent (top <= 0), then the parent must be clipped exactly 'top'
|
||||
// pixels to show the expanding notification, while still taking the decreasing
|
||||
// notification clipTopAmount into consideration, so 'top + clipTopAmount'.
|
||||
int parentStartClipTopAmount = params.getParentStartClipTopAmount();
|
||||
if (startClipTopAmount != 0) {
|
||||
int clipTopAmount = (int) MathUtils.lerp(parentStartClipTopAmount,
|
||||
parentStartClipTopAmount - startClipTopAmount,
|
||||
interpolation);
|
||||
mNotificationParent.setClipTopAmount(clipTopAmount);
|
||||
}
|
||||
int parentClipTopAmount = Math.min(parentStartClipTopAmount,
|
||||
top + clipTopAmount);
|
||||
mNotificationParent.setClipTopAmount(parentClipTopAmount);
|
||||
|
||||
mNotificationParent.setExtraWidthForClipping(extraWidthForClipping);
|
||||
float clipBottom = Math.max(params.getBottom(),
|
||||
parentY + mNotificationParent.getActualHeight()
|
||||
@@ -2046,7 +2051,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
int minimumHeightForClipping = (int) (clipBottom - clipTop);
|
||||
mNotificationParent.setMinimumHeightForClipping(minimumHeightForClipping);
|
||||
} else if (startClipTopAmount != 0) {
|
||||
int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, interpolation);
|
||||
setClipTopAmount(clipTopAmount);
|
||||
}
|
||||
setTranslationY(top);
|
||||
|
||||
@@ -34,7 +34,6 @@ import android.widget.RemoteViews;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.widget.CachingIconView;
|
||||
import com.android.internal.widget.NotificationExpandButton;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.CrossFadeHelper;
|
||||
@@ -638,10 +637,6 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
childState.location = parentState.location;
|
||||
childState.inShelf = parentState.inShelf;
|
||||
yPosition += intrinsicHeight;
|
||||
if (child.isExpandAnimationRunning()) {
|
||||
launchTransitionCompensation = -ambientState.getExpandAnimationTopChange();
|
||||
}
|
||||
|
||||
}
|
||||
if (mOverflowNumber != null) {
|
||||
ExpandableNotificationRow overflowView = mAttachedChildren.get(Math.min(
|
||||
|
||||
@@ -28,14 +28,12 @@ import android.view.ViewGroup;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.EmptyShadeView;
|
||||
import com.android.systemui.statusbar.NotificationShelf;
|
||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
||||
import com.android.systemui.statusbar.notification.row.FooterView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -156,7 +154,7 @@ public class StackScrollAlgorithm {
|
||||
private void updateClipping(StackScrollAlgorithmState algorithmState,
|
||||
AmbientState ambientState) {
|
||||
float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding()
|
||||
+ ambientState.getStackTranslation() + ambientState.getExpandAnimationTopChange()
|
||||
+ ambientState.getStackTranslation()
|
||||
: 0;
|
||||
float clipStart = 0;
|
||||
int childCount = algorithmState.visibleChildren.size();
|
||||
@@ -329,9 +327,6 @@ public class StackScrollAlgorithm {
|
||||
childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
|
||||
float inset = ambientState.getTopPadding() + ambientState.getStackTranslation()
|
||||
+ ambientState.getSectionPadding();
|
||||
if (i <= algorithmState.getIndexOfExpandingNotification()) {
|
||||
inset += ambientState.getExpandAnimationTopChange();
|
||||
}
|
||||
if (child.mustStayOnScreen() && childViewState.yTranslation >= 0) {
|
||||
// Even if we're not scrolled away we're in view and we're also not in the
|
||||
// shelf. We can relax the constraints and let us scroll off the top!
|
||||
|
||||
@@ -439,7 +439,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
|
||||
private boolean mUserSetupComplete;
|
||||
private int mQsNotificationTopPadding;
|
||||
private float mExpandOffset;
|
||||
private boolean mHideIconsDuringNotificationLaunch = true;
|
||||
private int mStackScrollerMeasuringPass;
|
||||
private ArrayList<Consumer<ExpandableNotificationRow>>
|
||||
@@ -2446,8 +2445,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
startHeight = -mQs.getQsMinExpansionHeight();
|
||||
}
|
||||
float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount))
|
||||
+ mExpandOffset;
|
||||
float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount));
|
||||
return Math.min(0, translation);
|
||||
}
|
||||
|
||||
@@ -3187,16 +3185,16 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
|
||||
public void applyExpandAnimationParams(ExpandAnimationParameters params) {
|
||||
mExpandOffset = params != null ? params.getTopChange() : 0;
|
||||
updateQsExpansion();
|
||||
if (params != null) {
|
||||
boolean hideIcons = params.getProgress(
|
||||
ActivityLaunchAnimator.ANIMATION_DELAY_ICON_FADE_IN, 100) == 0.0f;
|
||||
if (hideIcons != mHideIconsDuringNotificationLaunch) {
|
||||
mHideIconsDuringNotificationLaunch = hideIcons;
|
||||
if (!hideIcons) {
|
||||
mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
|
||||
}
|
||||
if (params == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hideIcons = params.getProgress(
|
||||
ActivityLaunchAnimator.ANIMATION_DELAY_ICON_FADE_IN, 100) == 0.0f;
|
||||
if (hideIcons != mHideIconsDuringNotificationLaunch) {
|
||||
mHideIconsDuringNotificationLaunch = hideIcons;
|
||||
if (!hideIcons) {
|
||||
mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,30 +89,22 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
// Invert the order of the scroll view and user switcher such that the notifications receive
|
||||
// touches first but the panel gets drawn above.
|
||||
mDrawingOrderedChildren.clear();
|
||||
mLayoutDrawingOrder.clear();
|
||||
if (mKeyguardStatusBar.getVisibility() == View.VISIBLE) {
|
||||
mDrawingOrderedChildren.add(mKeyguardStatusBar);
|
||||
mLayoutDrawingOrder.add(mKeyguardStatusBar);
|
||||
}
|
||||
if (mStackScroller.getVisibility() == View.VISIBLE) {
|
||||
mDrawingOrderedChildren.add(mStackScroller);
|
||||
mLayoutDrawingOrder.add(mStackScroller);
|
||||
}
|
||||
if (mQsFrame.getVisibility() == View.VISIBLE) {
|
||||
mDrawingOrderedChildren.add(mQsFrame);
|
||||
mLayoutDrawingOrder.add(mQsFrame);
|
||||
}
|
||||
|
||||
if (mHasViewsAboveShelf) {
|
||||
// StackScroller needs to be on top
|
||||
mDrawingOrderedChildren.remove(mStackScroller);
|
||||
if (mStackScroller.getVisibility() == View.VISIBLE) {
|
||||
mDrawingOrderedChildren.add(mStackScroller);
|
||||
mLayoutDrawingOrder.add(mStackScroller);
|
||||
}
|
||||
|
||||
// Let's now find the order that the view has when drawing regulary by sorting
|
||||
// Let's now find the order that the view has when drawing regularly by sorting
|
||||
mLayoutDrawingOrder.sort(mIndexComparator);
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
@@ -356,9 +356,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
||||
if (isActivityIntent || canBubble) {
|
||||
mAssistManagerLazy.get().hideAssist();
|
||||
}
|
||||
if (shouldCollapse()) {
|
||||
collapseOnMainThread();
|
||||
}
|
||||
|
||||
NotificationVisibility.NotificationLocation location =
|
||||
NotificationLogger.getNotificationLocation(entry);
|
||||
@@ -408,6 +405,12 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
||||
mMainThreadHandler.post(
|
||||
() -> mBubblesManagerOptional.get().expandStackAndSelectBubble(entry));
|
||||
}
|
||||
|
||||
// expandStackAndSelectBubble won't affect shouldCollapse, so we can collapse directly even
|
||||
// if we are not on the main thread.
|
||||
if (shouldCollapse()) {
|
||||
collapseOnMainThread();
|
||||
}
|
||||
}
|
||||
|
||||
private void startNotificationIntent(
|
||||
@@ -438,6 +441,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
||||
null, null, options);
|
||||
mMainThreadHandler.post(() -> {
|
||||
mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
|
||||
if (shouldCollapse()) {
|
||||
collapseOnMainThread();
|
||||
}
|
||||
});
|
||||
} catch (RemoteException | PendingIntent.CanceledException e) {
|
||||
// the stack trace isn't very helpful here.
|
||||
@@ -465,11 +471,11 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
||||
mActivityLaunchAnimator.setLaunchResult(launchResult,
|
||||
true /* isActivityIntent */);
|
||||
removeHUN(row);
|
||||
if (shouldCollapse()) {
|
||||
mCommandQueue.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
|
||||
true /* force */);
|
||||
}
|
||||
});
|
||||
if (shouldCollapse()) {
|
||||
mMainThreadHandler.post(() -> mCommandQueue.animateCollapsePanels(
|
||||
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}, null, false /* afterKeyguardGone */);
|
||||
|
||||
Reference in New Issue
Block a user