Update clear all animation
- Fade out clear all button on tap
- Fade out silent label once there are no silent notifs
- Fade out footer once there are no notifs
- Round corners of dismissing notifs
- Pause to show "no notifications" before closing shade
Timing
- Remove wait before clear all swipe animations start
- Wait less between individual swipe animations
- Faster swipe animation
Bug: 172065269
Test: clear all with scroll, silent notifs, no ongoing notifs
=> clear button fades out on tap
=> clearable notifs swipe out with new delay, timing
=> silent header fades
=> no scroll change
=> show "no notifications" at top of shade
=> close shade
Test: clear all with no scroll, ongoing silent notifs
=> clearable silent notifs swipe out
=> ongoing silent notifs stay
=> silent header "x" fades
=> show "no notifications" at top of shade
=> close shade
Test: clear a lot of notifications
=> pause same amount of time after swipe animations
before closing shade
Test: press "x" to clear silent notifications
=> silent notifications animate away
=> shade stays open if there are other clearable notifs
Change-Id: I4db85068f46b95a34e71abb6428d3c2ae757cf0a
Merged-In: I4db85068f46b95a34e71abb6428d3c2ae757cf0a
This commit is contained in:
@@ -437,6 +437,12 @@ public class SwipeHelper implements Gefingerpoken {
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
private boolean mCancelled;
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
super.onAnimationStart(animation);
|
||||
mCallback.onBeginDrag(animView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
mCancelled = true;
|
||||
|
||||
@@ -85,23 +85,26 @@ public abstract class StackScrollerDecorView extends ExpandableView {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content of this view to be visible in an animated way.
|
||||
*
|
||||
* @param contentVisible True if the content should be visible or false if it should be hidden.
|
||||
* @param visible True if we should animate contents visible
|
||||
*/
|
||||
public void setContentVisible(boolean contentVisible) {
|
||||
setContentVisible(contentVisible, true /* animate */);
|
||||
public void setContentVisible(boolean visible) {
|
||||
setContentVisible(visible, true /* animate */, null /* runAfter */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content of this view to be visible.
|
||||
* @param contentVisible True if the content should be visible or false if it should be hidden.
|
||||
* @param animate Should an animation be performed.
|
||||
* @param visible True if the contents should be visible
|
||||
* @param animate True if we should fade to new visibility
|
||||
* @param runAfter Runnable to run after visibility updates
|
||||
*/
|
||||
private void setContentVisible(boolean contentVisible, boolean animate) {
|
||||
if (mContentVisible != contentVisible) {
|
||||
public void setContentVisible(boolean visible, boolean animate, Runnable runAfter) {
|
||||
if (mContentVisible != visible) {
|
||||
mContentAnimating = animate;
|
||||
mContentVisible = contentVisible;
|
||||
setViewVisible(mContent, contentVisible, animate, mContentVisibilityEndRunnable);
|
||||
mContentVisible = visible;
|
||||
Runnable endRunnable = runAfter == null ? mContentVisibilityEndRunnable : () -> {
|
||||
mContentVisibilityEndRunnable.run();
|
||||
runAfter.run();
|
||||
};
|
||||
setViewVisible(mContent, visible, animate, endRunnable);
|
||||
}
|
||||
|
||||
if (!mContentAnimating) {
|
||||
@@ -113,6 +116,10 @@ public abstract class StackScrollerDecorView extends ExpandableView {
|
||||
return mContentVisible;
|
||||
}
|
||||
|
||||
public void setVisible(boolean nowVisible, boolean animate) {
|
||||
setVisible(nowVisible, animate, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this view visible. If {@code false} is passed, the view will fade out it's content
|
||||
* and set the view Visibility to GONE. If only the content should be changed
|
||||
@@ -121,7 +128,7 @@ public abstract class StackScrollerDecorView extends ExpandableView {
|
||||
* @param nowVisible should the view be visible
|
||||
* @param animate should the change be animated.
|
||||
*/
|
||||
public void setVisible(boolean nowVisible, boolean animate) {
|
||||
public void setVisible(boolean nowVisible, boolean animate, Runnable runAfter) {
|
||||
if (mIsVisible != nowVisible) {
|
||||
mIsVisible = nowVisible;
|
||||
if (animate) {
|
||||
@@ -132,10 +139,10 @@ public abstract class StackScrollerDecorView extends ExpandableView {
|
||||
} else {
|
||||
setWillBeGone(true);
|
||||
}
|
||||
setContentVisible(nowVisible, true /* animate */);
|
||||
setContentVisible(nowVisible, true /* animate */, runAfter);
|
||||
} else {
|
||||
setVisibility(nowVisible ? VISIBLE : GONE);
|
||||
setContentVisible(nowVisible, false /* animate */);
|
||||
setContentVisible(nowVisible, false /* animate */, runAfter);
|
||||
setWillBeGone(false);
|
||||
notifyHeightChanged(false /* needsAnimation */);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ public class NotificationRoundnessManager {
|
||||
private Runnable mRoundingChangedCallback;
|
||||
private ExpandableNotificationRow mTrackedHeadsUp;
|
||||
private float mAppearFraction;
|
||||
private boolean mIsDismissAllInProgress;
|
||||
|
||||
private ExpandableView mSwipedView = null;
|
||||
private ExpandableView mViewBeforeSwipedView = null;
|
||||
@@ -162,6 +163,10 @@ public class NotificationRoundnessManager {
|
||||
}
|
||||
}
|
||||
|
||||
void setDismissAllInProgress(boolean isClearingAll) {
|
||||
mIsDismissAllInProgress = isClearingAll;
|
||||
}
|
||||
|
||||
private float getRoundness(ExpandableView view, boolean top) {
|
||||
if (view == null) {
|
||||
return 0f;
|
||||
@@ -171,6 +176,11 @@ public class NotificationRoundnessManager {
|
||||
|| view == mViewAfterSwipedView) {
|
||||
return 1f;
|
||||
}
|
||||
if (view instanceof ExpandableNotificationRow
|
||||
&& ((ExpandableNotificationRow) view).canViewBeDismissed()
|
||||
&& mIsDismissAllInProgress) {
|
||||
return 1.0f;
|
||||
}
|
||||
if ((view.isPinned()
|
||||
|| (view.isHeadsUpAnimatingAway()) && !mExpanded)) {
|
||||
return 1.0f;
|
||||
|
||||
@@ -144,6 +144,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
private static final boolean DEBUG_REMOVE_ANIMATION = SystemProperties.getBoolean(
|
||||
"persist.debug.nssl.dismiss", false /* default */);
|
||||
|
||||
// Delay in milli-seconds before shade closes for clear all.
|
||||
private final int DELAY_BEFORE_SHADE_CLOSE = 200;
|
||||
private boolean mShadeNeedsToClose = false;
|
||||
|
||||
private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
|
||||
private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f;
|
||||
private static final float RUBBER_BAND_FACTOR_ON_PANEL_EXPAND = 0.21f;
|
||||
@@ -259,7 +263,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
protected FooterView mFooterView;
|
||||
protected EmptyShadeView mEmptyShadeView;
|
||||
private boolean mDismissAllInProgress;
|
||||
private boolean mFadeNotificationsOnDismiss;
|
||||
private FooterDismissListener mFooterDismissListener;
|
||||
private boolean mFlingAfterUpEvent;
|
||||
|
||||
@@ -1192,7 +1195,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
|
||||
private void clampScrollPosition() {
|
||||
int scrollRange = getScrollRange();
|
||||
if (scrollRange < mOwnScrollY) {
|
||||
if (scrollRange < mOwnScrollY && !mAmbientState.isDismissAllInProgress()) {
|
||||
boolean animateStackY = false;
|
||||
if (scrollRange < getScrollAmountToScrollBoundary()
|
||||
&& mAnimateStackYForContentHeightChange) {
|
||||
@@ -1708,6 +1711,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
||||
public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) {
|
||||
if (child instanceof SectionHeaderView) {
|
||||
((StackScrollerDecorView) child).setContentVisible(
|
||||
false /* visible */, true /* animate */, endRunnable);
|
||||
return;
|
||||
}
|
||||
mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration,
|
||||
true /* isDismissAll */);
|
||||
}
|
||||
@@ -4050,6 +4058,19 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
runAnimationFinishedRunnables();
|
||||
clearTransient();
|
||||
clearHeadsUpDisappearRunning();
|
||||
|
||||
if (mAmbientState.isDismissAllInProgress()) {
|
||||
setDismissAllInProgress(false);
|
||||
|
||||
if (mShadeNeedsToClose) {
|
||||
mShadeNeedsToClose = false;
|
||||
postDelayed(
|
||||
() -> {
|
||||
mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
|
||||
},
|
||||
DELAY_BEFORE_SHADE_CLOSE /* delayMillis */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
||||
@@ -4407,6 +4428,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
public void setDismissAllInProgress(boolean dismissAllInProgress) {
|
||||
mDismissAllInProgress = dismissAllInProgress;
|
||||
mAmbientState.setDismissAllInProgress(dismissAllInProgress);
|
||||
mController.getNoticationRoundessManager().setDismissAllInProgress(dismissAllInProgress);
|
||||
handleDismissAllClipping();
|
||||
}
|
||||
|
||||
@@ -4947,64 +4969,129 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
mHeadsUpAppearanceController = headsUpAppearanceController;
|
||||
}
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||
@VisibleForTesting
|
||||
void clearNotifications(@SelectedRows int selection, boolean closeShade) {
|
||||
// animate-swipe all dismissable notifications, then animate the shade closed
|
||||
int numChildren = getChildCount();
|
||||
private boolean isVisible(View child) {
|
||||
boolean hasClipBounds = child.getClipBounds(mTmpRect);
|
||||
return child.getVisibility() == View.VISIBLE
|
||||
&& (!hasClipBounds || mTmpRect.height() > 0);
|
||||
}
|
||||
|
||||
final ArrayList<View> viewsToHide = new ArrayList<>(numChildren);
|
||||
final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren);
|
||||
for (int i = 0; i < numChildren; i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||
boolean parentVisible = false;
|
||||
boolean hasClipBounds = child.getClipBounds(mTmpRect);
|
||||
if (includeChildInDismissAll(row, selection)) {
|
||||
viewsToRemove.add(row);
|
||||
if (child.getVisibility() == View.VISIBLE
|
||||
&& (!hasClipBounds || mTmpRect.height() > 0)) {
|
||||
viewsToHide.add(child);
|
||||
parentVisible = true;
|
||||
}
|
||||
} else if (child.getVisibility() == View.VISIBLE
|
||||
&& (!hasClipBounds || mTmpRect.height() > 0)) {
|
||||
parentVisible = true;
|
||||
}
|
||||
List<ExpandableNotificationRow> children = row.getAttachedChildren();
|
||||
if (children != null) {
|
||||
for (ExpandableNotificationRow childRow : children) {
|
||||
if (includeChildInDismissAll(row, selection)) {
|
||||
viewsToRemove.add(childRow);
|
||||
if (parentVisible && row.areChildrenExpanded()) {
|
||||
hasClipBounds = childRow.getClipBounds(mTmpRect);
|
||||
if (childRow.getVisibility() == View.VISIBLE
|
||||
&& (!hasClipBounds || mTmpRect.height() > 0)) {
|
||||
viewsToHide.add(childRow);
|
||||
}
|
||||
}
|
||||
private boolean shouldHideParent(View view, @SelectedRows int selection) {
|
||||
final boolean silentSectionWillBeGone =
|
||||
!mController.hasNotifications(ROWS_GENTLE, false /* clearable */);
|
||||
|
||||
// The only SectionHeaderView we have is the silent section header.
|
||||
if (view instanceof SectionHeaderView && silentSectionWillBeGone) {
|
||||
return true;
|
||||
}
|
||||
if (view instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
|
||||
if (isVisible(row) && includeChildInDismissAll(row, selection)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isChildrenVisible(ExpandableNotificationRow parent) {
|
||||
List<ExpandableNotificationRow> children = parent.getAttachedChildren();
|
||||
return isVisible(parent)
|
||||
&& children != null
|
||||
&& parent.areChildrenExpanded();
|
||||
}
|
||||
|
||||
// Similar to #getRowsToDismissInBackend, but filters for visible views.
|
||||
private ArrayList<View> getVisibleViewsToAnimateAway(@SelectedRows int selection) {
|
||||
final int viewCount = getChildCount();
|
||||
final ArrayList<View> viewsToHide = new ArrayList<>(viewCount);
|
||||
|
||||
for (int i = 0; i < viewCount; i++) {
|
||||
final View view = getChildAt(i);
|
||||
|
||||
if (shouldHideParent(view, selection)) {
|
||||
viewsToHide.add(view);
|
||||
}
|
||||
if (view instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
|
||||
|
||||
if (isChildrenVisible(parent)) {
|
||||
for (ExpandableNotificationRow child : parent.getAttachedChildren()) {
|
||||
if (isVisible(child) && includeChildInDismissAll(child, selection)) {
|
||||
viewsToHide.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return viewsToHide;
|
||||
}
|
||||
|
||||
private ArrayList<ExpandableNotificationRow> getRowsToDismissInBackend(
|
||||
@SelectedRows int selection) {
|
||||
final int childCount = getChildCount();
|
||||
final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(childCount);
|
||||
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final View view = getChildAt(i);
|
||||
if (!(view instanceof ExpandableNotificationRow)) {
|
||||
continue;
|
||||
}
|
||||
ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
|
||||
if (includeChildInDismissAll(parent, selection)) {
|
||||
viewsToRemove.add(parent);
|
||||
}
|
||||
List<ExpandableNotificationRow> children = parent.getAttachedChildren();
|
||||
if (isVisible(parent) && children != null) {
|
||||
for (ExpandableNotificationRow child : children) {
|
||||
if (includeChildInDismissAll(parent, selection)) {
|
||||
viewsToRemove.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return viewsToRemove;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects a list of visible rows, and animates them away in a staggered fashion as if they
|
||||
* were dismissed. Notifications are dismissed in the backend via onDismissAllAnimationsEnd.
|
||||
*/
|
||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||
@VisibleForTesting
|
||||
void clearNotifications(@SelectedRows int selection, boolean closeShade) {
|
||||
// Animate-swipe all dismissable notifications, then animate the shade closed
|
||||
final ArrayList<View> viewsToAnimateAway = getVisibleViewsToAnimateAway(selection);
|
||||
final ArrayList<ExpandableNotificationRow> rowsToDismissInBackend =
|
||||
getRowsToDismissInBackend(selection);
|
||||
if (mDismissListener != null) {
|
||||
mDismissListener.onDismiss(selection);
|
||||
}
|
||||
|
||||
if (viewsToRemove.isEmpty()) {
|
||||
if (closeShade && mShadeController != null) {
|
||||
mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
|
||||
}
|
||||
final Runnable dismissInBackend = () -> {
|
||||
onDismissAllAnimationsEnd(rowsToDismissInBackend, selection);
|
||||
};
|
||||
if (viewsToAnimateAway.isEmpty()) {
|
||||
dismissInBackend.run();
|
||||
return;
|
||||
}
|
||||
// Disable normal animations
|
||||
setDismissAllInProgress(true);
|
||||
mShadeNeedsToClose = closeShade;
|
||||
|
||||
performDismissAllAnimations(
|
||||
viewsToHide,
|
||||
closeShade,
|
||||
() -> onDismissAllAnimationsEnd(viewsToRemove, selection));
|
||||
// Decrease the delay for every row we animate to give the sense of
|
||||
// accelerating the swipes
|
||||
final int rowDelayDecrement = 5;
|
||||
int currentDelay = 60;
|
||||
int totalDelay = 0;
|
||||
final int numItems = viewsToAnimateAway.size();
|
||||
for (int i = numItems - 1; i >= 0; i--) {
|
||||
View view = viewsToAnimateAway.get(i);
|
||||
Runnable endRunnable = null;
|
||||
if (i == 0) {
|
||||
endRunnable = dismissInBackend;
|
||||
}
|
||||
dismissViewAnimated(view, endRunnable, totalDelay, ANIMATION_DURATION_SWIPE);
|
||||
currentDelay = Math.max(30, currentDelay - rowDelayDecrement);
|
||||
totalDelay += currentDelay;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean includeChildInDismissAll(
|
||||
@@ -5013,63 +5100,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
return canChildBeDismissed(row) && matchesSelection(row, selection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of rows, animates them away in a staggered fashion as if they were dismissed.
|
||||
* Doesn't actually dismiss them, though -- that must be done in the onAnimationComplete
|
||||
* handler.
|
||||
*
|
||||
* @param hideAnimatedList List of rows to animated away. Should only be views that are
|
||||
* currently visible, or else the stagger will look funky.
|
||||
* @param closeShade Whether to close the shade after the stagger animation completes.
|
||||
* @param onAnimationComplete Called after the entire animation completes (including the shade
|
||||
* closing if appropriate). The rows must be dismissed for real here.
|
||||
*/
|
||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||
private void performDismissAllAnimations(
|
||||
final ArrayList<View> hideAnimatedList,
|
||||
final boolean closeShade,
|
||||
final Runnable onAnimationComplete) {
|
||||
|
||||
final Runnable onSlideAwayAnimationComplete = () -> {
|
||||
if (closeShade) {
|
||||
mShadeController.addPostCollapseAction(() -> {
|
||||
setDismissAllInProgress(false);
|
||||
onAnimationComplete.run();
|
||||
});
|
||||
mShadeController.animateCollapsePanels(
|
||||
CommandQueue.FLAG_EXCLUDE_NONE);
|
||||
} else {
|
||||
setDismissAllInProgress(false);
|
||||
onAnimationComplete.run();
|
||||
}
|
||||
};
|
||||
|
||||
if (hideAnimatedList.isEmpty()) {
|
||||
onSlideAwayAnimationComplete.run();
|
||||
return;
|
||||
}
|
||||
|
||||
// let's disable our normal animations
|
||||
setDismissAllInProgress(true);
|
||||
|
||||
// Decrease the delay for every row we animate to give the sense of
|
||||
// accelerating the swipes
|
||||
int rowDelayDecrement = 10;
|
||||
int currentDelay = 140;
|
||||
int totalDelay = 180;
|
||||
int numItems = hideAnimatedList.size();
|
||||
for (int i = numItems - 1; i >= 0; i--) {
|
||||
View view = hideAnimatedList.get(i);
|
||||
Runnable endRunnable = null;
|
||||
if (i == 0) {
|
||||
endRunnable = onSlideAwayAnimationComplete;
|
||||
}
|
||||
dismissViewAnimated(view, endRunnable, totalDelay, ANIMATION_DURATION_SWIPE);
|
||||
currentDelay = Math.max(50, currentDelay - rowDelayDecrement);
|
||||
totalDelay += currentDelay;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNotificationActivityStarter(
|
||||
NotificationActivityStarter notificationActivityStarter) {
|
||||
mNotificationActivityStarter = notificationActivityStarter;
|
||||
@@ -5085,6 +5115,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
mFooterDismissListener.onDismiss();
|
||||
}
|
||||
clearNotifications(ROWS_ALL, true /* closeShade */);
|
||||
footerView.setSecondaryVisible(false /* visible */, true /* animate */);
|
||||
});
|
||||
footerView.setManageButtonClickListener(v -> {
|
||||
mNotificationActivityStarter.startHistoryIntent(v, mFooterView.isHistoryShown());
|
||||
|
||||
@@ -1122,6 +1122,10 @@ public class NotificationStackScrollLayoutController {
|
||||
mZenModeController.areNotificationsHiddenInShade());
|
||||
}
|
||||
|
||||
public boolean areNotificationsHiddenInShade() {
|
||||
return mZenModeController.areNotificationsHiddenInShade();
|
||||
}
|
||||
|
||||
public boolean isShowingEmptyShadeView() {
|
||||
return mShowEmptyShadeView;
|
||||
}
|
||||
@@ -1170,6 +1174,10 @@ public class NotificationStackScrollLayoutController {
|
||||
* Return whether there are any clearable notifications
|
||||
*/
|
||||
public boolean hasActiveClearableNotifications(@SelectedRows int selection) {
|
||||
return hasNotifications(selection, true /* clearable */);
|
||||
}
|
||||
|
||||
public boolean hasNotifications(@SelectedRows int selection, boolean isClearable) {
|
||||
if (mDynamicPrivacyController.isInLockedDownShade()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1180,8 +1188,11 @@ public class NotificationStackScrollLayoutController {
|
||||
continue;
|
||||
}
|
||||
final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||
if (row.canViewBeDismissed() &&
|
||||
NotificationStackScrollLayout.matchesSelection(row, selection)) {
|
||||
final boolean matchClearable =
|
||||
isClearable ? row.canViewBeDismissed() : !row.canViewBeDismissed();
|
||||
final boolean inSection =
|
||||
NotificationStackScrollLayout.matchesSelection(row, selection);
|
||||
if (matchClearable && inSection) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,6 +366,20 @@ public class StackScrollAlgorithm {
|
||||
return stackHeight / stackEndHeight;
|
||||
}
|
||||
|
||||
public boolean hasOngoingNotifs(StackScrollAlgorithmState algorithmState) {
|
||||
for (int i = 0; i < algorithmState.visibleChildren.size(); i++) {
|
||||
View child = algorithmState.visibleChildren.get(i);
|
||||
if (!(child instanceof ExpandableNotificationRow)) {
|
||||
continue;
|
||||
}
|
||||
final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||
if (!row.canViewBeDismissed()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(b/172289889) polish shade open from HUN
|
||||
/**
|
||||
* Populates the {@link ExpandableViewState} for a single child.
|
||||
@@ -430,7 +444,9 @@ public class StackScrollAlgorithm {
|
||||
+ view.getIntrinsicHeight();
|
||||
final boolean noSpaceForFooter = footerEnd > ambientState.getStackEndHeight();
|
||||
((FooterView.FooterViewState) viewState).hideContent =
|
||||
isShelfShowing || noSpaceForFooter;
|
||||
isShelfShowing || noSpaceForFooter
|
||||
|| (ambientState.isDismissAllInProgress()
|
||||
&& !hasOngoingNotifs(algorithmState));
|
||||
}
|
||||
} else {
|
||||
if (view != ambientState.getTrackedHeadsUpRow()) {
|
||||
@@ -467,7 +483,6 @@ public class StackScrollAlgorithm {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clip height of view right before shelf.
|
||||
viewState.height = (int) (getMaxAllowedChildHeight(view) * expansionFraction);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class StackStateAnimator {
|
||||
public static final int ANIMATION_DURATION_WAKEUP = 500;
|
||||
public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
|
||||
public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
|
||||
public static final int ANIMATION_DURATION_SWIPE = 260;
|
||||
public static final int ANIMATION_DURATION_SWIPE = 200;
|
||||
public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
|
||||
public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150;
|
||||
public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 400;
|
||||
|
||||
@@ -310,17 +310,11 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
private void onNotificationRemoved(String key, StatusBarNotification old, int reason) {
|
||||
if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
|
||||
|
||||
if (old != null) {
|
||||
if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
|
||||
&& !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) {
|
||||
if (mStatusBarStateController.getState() == StatusBarState.SHADE
|
||||
&& reason != NotificationListenerService.REASON_CLICK) {
|
||||
mCommandQueue.animateCollapsePanels();
|
||||
} else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
|
||||
if (old != null && CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
|
||||
&& !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()
|
||||
&& mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
|
||||
&& !isCollapsing()) {
|
||||
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
|
||||
}
|
||||
}
|
||||
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user