diff options
11 files changed, 293 insertions, 154 deletions
diff --git a/packages/SystemUI/res/layout/people_strip.xml b/packages/SystemUI/res/layout/people_strip.xml index c2dbacaa64f7..f5ed1032df6c 100644 --- a/packages/SystemUI/res/layout/people_strip.xml +++ b/packages/SystemUI/res/layout/people_strip.xml @@ -31,13 +31,16 @@ android:layout_height="match_parent" android:layout_marginEnd="8dp" android:gravity="bottom" - android:orientation="horizontal"> + android:orientation="horizontal" + android:forceHasOverlappingRendering="false" + android:clipChildren="false"> <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="start|center_vertical" - android:layout_weight="1"> + android:layout_weight="1" + android:forceHasOverlappingRendering="false"> <TextView style="@style/TextAppearance.NotificationSectionHeaderButton" @@ -53,6 +56,7 @@ android:layout_height="48dp" android:padding="8dp" android:scaleType="fitCenter" + android:forceHasOverlappingRendering="false" /> <ImageView @@ -60,6 +64,7 @@ android:layout_height="48dp" android:padding="8dp" android:scaleType="fitCenter" + android:forceHasOverlappingRendering="false" /> <ImageView @@ -67,6 +72,7 @@ android:layout_height="48dp" android:padding="8dp" android:scaleType="fitCenter" + android:forceHasOverlappingRendering="false" /> <ImageView @@ -74,6 +80,7 @@ android:layout_height="48dp" android:padding="8dp" android:scaleType="fitCenter" + android:forceHasOverlappingRendering="false" /> <ImageView @@ -81,6 +88,7 @@ android:layout_height="48dp" android:padding="8dp" android:scaleType="fitCenter" + android:forceHasOverlappingRendering="false" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml index 0043d7a7bdad..44c409e08e82 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml @@ -32,6 +32,8 @@ android:layout_gravity="bottom" android:gravity="center_vertical" android:orientation="horizontal" + android:forceHasOverlappingRendering="false" + android:clipChildren="false" > <include layout="@layout/status_bar_notification_section_header_contents"/> </LinearLayout> diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml index df4b0471c78b..3b9c44d1b5df 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml @@ -27,6 +27,7 @@ android:id="@+id/header_label" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:forceHasOverlappingRendering="false" android:text="@string/notification_section_header_gentle" /> @@ -41,5 +42,6 @@ android:tint="?attr/wallpaperTextColor" android:tintMode="src_in" android:visibility="gone" + android:forceHasOverlappingRendering="false" /> </merge> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 016b48bb48a1..4f803bccfb25 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -184,8 +184,8 @@ <!-- Vertical translation of pulsing notification animations --> <dimen name="pulsing_notification_appear_translation">10dp</dimen> - <!-- The amount the content shifts upwards when transforming into the icon --> - <dimen name="notification_icon_transform_content_shift">32dp</dimen> + <!-- The amount the content shifts upwards when transforming into the shelf --> + <dimen name="shelf_transform_content_shift">32dp</dimen> <!-- The padding on the bottom of the notifications on the keyguard --> <dimen name="keyguard_indication_bottom_padding">12sp</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 882a88bbdb75..1a8454cfa113 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -273,47 +273,37 @@ public class NotificationShelf extends ActivatableNotificationView implements int backgroundTop = 0; int clipTopAmount = 0; float firstElementRoundness = 0.0f; - ActivatableNotificationView previousRow = null; + ActivatableNotificationView previousAnv = null; for (int i = 0; i < mHostLayout.getChildCount(); i++) { ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i); - if (!(child instanceof ActivatableNotificationView) - || child.getVisibility() == GONE || child == this) { + if (!child.needsClippingToShelf() || child.getVisibility() == GONE) { continue; } - ActivatableNotificationView row = (ActivatableNotificationView) child; float notificationClipEnd; - boolean aboveShelf = ViewState.getFinalTranslationZ(row) > baseZHeight - || row.isPinned(); + boolean aboveShelf = ViewState.getFinalTranslationZ(child) > baseZHeight + || child.isPinned(); boolean isLastChild = child == lastChild; - float rowTranslationY = row.getTranslationY(); + float rowTranslationY = child.getTranslationY(); if ((isLastChild && !child.isInShelf()) || aboveShelf || backgroundForceHidden) { notificationClipEnd = shelfStart + getIntrinsicHeight(); } else { notificationClipEnd = shelfStart - mPaddingBetweenElements; - float height = notificationClipEnd - rowTranslationY; - if (!row.isBelowSpeedBump() && height <= getNotificationMergeSize()) { - // We want the gap to close when we reached the minimum size and only shrink - // before - notificationClipEnd = Math.min(shelfStart, - rowTranslationY + getNotificationMergeSize()); - } } - int clipTop = updateNotificationClipHeight(row, notificationClipEnd, notGoneIndex); + int clipTop = updateNotificationClipHeight(child, notificationClipEnd, notGoneIndex); clipTopAmount = Math.max(clipTop, clipTopAmount); + + float inShelfAmount = updateShelfTransformation(child, expandAmount, scrolling, + scrollingFast, expandingAnimated, isLastChild); // If the current row is an ExpandableNotificationRow, update its color, roundedness, // and icon state. - if (row instanceof ExpandableNotificationRow) { - ExpandableNotificationRow expandableRow = (ExpandableNotificationRow) row; - - float inShelfAmount = updateIconAppearance(expandableRow, expandAmount, scrolling, - scrollingFast, - expandingAnimated, isLastChild); + if (child instanceof ExpandableNotificationRow) { + ExpandableNotificationRow expandableRow = (ExpandableNotificationRow) child; numViewsInShelf += inShelfAmount; - int ownColorUntinted = row.getBackgroundColorWithoutTint(); + int ownColorUntinted = expandableRow.getBackgroundColorWithoutTint(); if (rowTranslationY >= shelfStart && mNotGoneIndex == -1) { mNotGoneIndex = notGoneIndex; setTintColor(previousColor); @@ -330,10 +320,10 @@ public class NotificationShelf extends ActivatableNotificationView implements if (colorOfViewBeforeLast == NO_COLOR) { colorOfViewBeforeLast = ownColorUntinted; } - row.setOverrideTintColor(colorOfViewBeforeLast, inShelfAmount); + expandableRow.setOverrideTintColor(colorOfViewBeforeLast, inShelfAmount); } else { colorOfViewBeforeLast = ownColorUntinted; - row.setOverrideTintColor(NO_COLOR, 0 /* overrideAmount */); + expandableRow.setOverrideTintColor(NO_COLOR, 0 /* overrideAmount */); } if (notGoneIndex != 0 || !aboveShelf) { expandableRow.setAboveShelf(false); @@ -346,8 +336,8 @@ public class NotificationShelf extends ActivatableNotificationView implements // since they don't show up on AOD if (iconState != null && iconState.clampedAppearAmount == 1.0f) { // only if the first icon is fully in the shelf we want to clip to it! - backgroundTop = (int) (row.getTranslationY() - getTranslationY()); - firstElementRoundness = row.getCurrentTopRoundness(); + backgroundTop = (int) (child.getTranslationY() - getTranslationY()); + firstElementRoundness = expandableRow.getCurrentTopRoundness(); } } @@ -355,25 +345,31 @@ public class NotificationShelf extends ActivatableNotificationView implements notGoneIndex++; } - if (row.isFirstInSection() && previousRow != null && previousRow.isLastInSection()) { - // If the top of the shelf is between the view before a gap and the view after a gap - // then we need to adjust the shelf's top roundness. - float distanceToGapBottom = row.getTranslationY() - getTranslationY(); - float distanceToGapTop = getTranslationY() - - (previousRow.getTranslationY() + previousRow.getActualHeight()); - if (distanceToGapTop > 0) { - // We interpolate our top roundness so that it's fully rounded if we're at the - // bottom of the gap, and not rounded at all if we're at the top of the gap - // (directly up against the bottom of previousRow) - // Then we apply the same roundness to the bottom of previousRow so that the - // corners join together as the shelf approaches previousRow. - firstElementRoundness = (float) Math.min(1.0, distanceToGapTop / mGapHeight); - previousRow.setBottomRoundness(firstElementRoundness, - false /* don't animate */); - backgroundTop = (int) distanceToGapBottom; + if (child instanceof ActivatableNotificationView) { + ActivatableNotificationView anv = + (ActivatableNotificationView) child; + if (anv.isFirstInSection() && previousAnv != null + && previousAnv.isLastInSection()) { + // If the top of the shelf is between the view before a gap and the view after a + // gap then we need to adjust the shelf's top roundness. + float distanceToGapBottom = child.getTranslationY() - getTranslationY(); + float distanceToGapTop = getTranslationY() + - (previousAnv.getTranslationY() + previousAnv.getActualHeight()); + if (distanceToGapTop > 0) { + // We interpolate our top roundness so that it's fully rounded if we're at + // the bottom of the gap, and not rounded at all if we're at the top of the + // gap (directly up against the bottom of previousAnv) + // Then we apply the same roundness to the bottom of previousAnv so that the + // corners join together as the shelf approaches previousAnv. + firstElementRoundness = (float) Math.min(1.0, + distanceToGapTop / mGapHeight); + previousAnv.setBottomRoundness(firstElementRoundness, + false /* don't animate */); + backgroundTop = (int) distanceToGapBottom; + } } + previousAnv = anv; } - previousRow = row; } clipTransientViews(); @@ -493,27 +489,27 @@ public class NotificationShelf extends ActivatableNotificationView implements * Update the clipping of this view. * @return the amount that our own top should be clipped */ - private int updateNotificationClipHeight(ActivatableNotificationView row, + private int updateNotificationClipHeight(ExpandableView view, float notificationClipEnd, int childIndex) { - float viewEnd = row.getTranslationY() + row.getActualHeight(); - boolean isPinned = (row.isPinned() || row.isHeadsUpAnimatingAway()) - && !mAmbientState.isDozingAndNotPulsing(row); + float viewEnd = view.getTranslationY() + view.getActualHeight(); + boolean isPinned = (view.isPinned() || view.isHeadsUpAnimatingAway()) + && !mAmbientState.isDozingAndNotPulsing(view); boolean shouldClipOwnTop; if (mAmbientState.isPulseExpanding()) { shouldClipOwnTop = childIndex == 0; } else { - shouldClipOwnTop = row.showingPulsing(); + shouldClipOwnTop = view.showingPulsing(); } if (viewEnd > notificationClipEnd && !shouldClipOwnTop && (mAmbientState.isShadeExpanded() || !isPinned)) { int clipBottomAmount = (int) (viewEnd - notificationClipEnd); if (isPinned) { - clipBottomAmount = Math.min(row.getIntrinsicHeight() - row.getCollapsedHeight(), + clipBottomAmount = Math.min(view.getIntrinsicHeight() - view.getCollapsedHeight(), clipBottomAmount); } - row.setClipBottomAmount(clipBottomAmount); + view.setClipBottomAmount(clipBottomAmount); } else { - row.setClipBottomAmount(0); + view.setClipBottomAmount(0); } if (shouldClipOwnTop) { return (int) (viewEnd - getTranslationY()); @@ -532,31 +528,28 @@ public class NotificationShelf extends ActivatableNotificationView implements } /** - * @return the icon amount how much this notification is in the shelf; + * @return the amount how much this notification is in the shelf */ - private float updateIconAppearance(ExpandableNotificationRow row, float expandAmount, + private float updateShelfTransformation(ExpandableView view, float expandAmount, boolean scrolling, boolean scrollingFast, boolean expandingAnimated, boolean isLastChild) { - StatusBarIconView icon = row.getEntry().expandedIcon; + StatusBarIconView icon = view.getShelfIcon(); NotificationIconContainer.IconState iconState = getIconState(icon); - if (iconState == null) { - return 0.0f; - } // Let calculate how much the view is in the shelf - float viewStart = row.getTranslationY(); - int fullHeight = row.getActualHeight() + mPaddingBetweenElements; + float viewStart = view.getTranslationY(); + int fullHeight = view.getActualHeight() + mPaddingBetweenElements; float iconTransformDistance = getIntrinsicHeight() * 1.5f; iconTransformDistance *= NotificationUtils.interpolate(1.f, 1.5f, expandAmount); iconTransformDistance = Math.min(iconTransformDistance, fullHeight); if (isLastChild) { - fullHeight = Math.min(fullHeight, row.getMinHeight() - getIntrinsicHeight()); - iconTransformDistance = Math.min(iconTransformDistance, row.getMinHeight() + fullHeight = Math.min(fullHeight, view.getMinHeight() - getIntrinsicHeight()); + iconTransformDistance = Math.min(iconTransformDistance, view.getMinHeight() - getIntrinsicHeight()); } float viewEnd = viewStart + fullHeight; // TODO: fix this check for anchor scrolling. - if (expandingAnimated && mAmbientState.getScrollY() == 0 + if (iconState != null && expandingAnimated && mAmbientState.getScrollY() == 0 && !mAmbientState.isOnKeyguard() && !iconState.isLastExpandIcon) { // We are expanding animated. Because we switch to a linear interpolation in this case, // the last icon may be stuck in between the shelf position and the notification @@ -566,10 +559,10 @@ public class NotificationShelf extends ActivatableNotificationView implements // We need to persist this, since after the expansion, the behavior should still be the // same. float position = mAmbientState.getIntrinsicPadding() - + mHostLayout.getPositionInLinearLayout(row); + + mHostLayout.getPositionInLinearLayout(view); int maxShelfStart = mMaxLayoutHeight - getIntrinsicHeight(); - if (position < maxShelfStart && position + row.getIntrinsicHeight() >= maxShelfStart - && row.getTranslationY() < position) { + if (position < maxShelfStart && position + view.getIntrinsicHeight() >= maxShelfStart + && view.getTranslationY() < position) { iconState.isLastExpandIcon = true; iconState.customTransformHeight = NO_VALUE; // Let's check if we're close enough to snap into the shelf @@ -584,16 +577,16 @@ public class NotificationShelf extends ActivatableNotificationView implements } } float fullTransitionAmount; - float iconTransitionAmount; + float transitionAmount; float shelfStart = getTranslationY(); - if (iconState.hasCustomTransformHeight()) { + if (iconState != null && iconState.hasCustomTransformHeight()) { fullHeight = iconState.customTransformHeight; iconTransformDistance = iconState.customTransformHeight; } boolean fullyInOrOut = true; - if (viewEnd >= shelfStart && (!mAmbientState.isUnlockHintRunning() || row.isInShelf()) + if (viewEnd >= shelfStart && (!mAmbientState.isUnlockHintRunning() || view.isInShelf()) && (mAmbientState.isShadeExpanded() - || (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) { + || (!view.isPinned() && !view.isHeadsUpAnimatingAway()))) { if (viewStart < shelfStart) { float fullAmount = (shelfStart - viewStart) / fullHeight; fullAmount = Math.min(1.0f, fullAmount); @@ -603,88 +596,98 @@ public class NotificationShelf extends ActivatableNotificationView implements interpolatedAmount, fullAmount, expandAmount); fullTransitionAmount = 1.0f - interpolatedAmount; - iconTransitionAmount = (shelfStart - viewStart) / iconTransformDistance; - iconTransitionAmount = Math.min(1.0f, iconTransitionAmount); - iconTransitionAmount = 1.0f - iconTransitionAmount; + transitionAmount = (shelfStart - viewStart) / iconTransformDistance; + transitionAmount = Math.min(1.0f, transitionAmount); + transitionAmount = 1.0f - transitionAmount; fullyInOrOut = false; } else { fullTransitionAmount = 1.0f; - iconTransitionAmount = 1.0f; + transitionAmount = 1.0f; } } else { fullTransitionAmount = 0.0f; - iconTransitionAmount = 0.0f; + transitionAmount = 0.0f; } - if (fullyInOrOut && !expandingAnimated && iconState.isLastExpandIcon) { + if (iconState != null && fullyInOrOut && !expandingAnimated && iconState.isLastExpandIcon) { iconState.isLastExpandIcon = false; iconState.customTransformHeight = NO_VALUE; } - updateIconPositioning(row, iconTransitionAmount, fullTransitionAmount, + updateIconPositioning(view, transitionAmount, fullTransitionAmount, iconTransformDistance, scrolling, scrollingFast, expandingAnimated, isLastChild); return fullTransitionAmount; } - private void updateIconPositioning(ExpandableNotificationRow row, float iconTransitionAmount, + private void updateIconPositioning(ExpandableView view, float iconTransitionAmount, float fullTransitionAmount, float iconTransformDistance, boolean scrolling, boolean scrollingFast, boolean expandingAnimated, boolean isLastChild) { - StatusBarIconView icon = row.getEntry().expandedIcon; + StatusBarIconView icon = view.getShelfIcon(); NotificationIconContainer.IconState iconState = getIconState(icon); + float contentTransformationAmount; if (iconState == null) { - return; - } - boolean forceInShelf = iconState.isLastExpandIcon && !iconState.hasCustomTransformHeight(); - float clampedAmount = iconTransitionAmount > 0.5f ? 1.0f : 0.0f; - if (clampedAmount == fullTransitionAmount) { - iconState.noAnimations = (scrollingFast || expandingAnimated) && !forceInShelf; - iconState.useFullTransitionAmount = iconState.noAnimations - || (!ICON_ANMATIONS_WHILE_SCROLLING && fullTransitionAmount == 0.0f && scrolling); - iconState.useLinearTransitionAmount = !ICON_ANMATIONS_WHILE_SCROLLING - && fullTransitionAmount == 0.0f && !mAmbientState.isExpansionChanging(); - iconState.translateContent = mMaxLayoutHeight - getTranslationY() - - getIntrinsicHeight() > 0; - } - if (!forceInShelf && (scrollingFast || (expandingAnimated - && iconState.useFullTransitionAmount && !ViewState.isAnimatingY(icon)))) { - iconState.cancelAnimations(icon); - iconState.useFullTransitionAmount = true; - iconState.noAnimations = true; - } - if (iconState.hasCustomTransformHeight()) { - iconState.useFullTransitionAmount = true; - } - if (iconState.isLastExpandIcon) { - iconState.translateContent = false; - } - float transitionAmount; - if (mAmbientState.isHiddenAtAll() && !row.isInShelf()) { - transitionAmount = mAmbientState.isFullyHidden() ? 1 : 0; - } else if (isLastChild || !USE_ANIMATIONS_WHEN_OPENING || iconState.useFullTransitionAmount - || iconState.useLinearTransitionAmount) { - transitionAmount = iconTransitionAmount; + contentTransformationAmount = iconTransitionAmount; } else { - // We take the clamped position instead - transitionAmount = clampedAmount; - iconState.needsCannedAnimation = iconState.clampedAppearAmount != clampedAmount - && !mNoAnimationsInThisFrame; - } - iconState.iconAppearAmount = !USE_ANIMATIONS_WHEN_OPENING + boolean forceInShelf = + iconState.isLastExpandIcon && !iconState.hasCustomTransformHeight(); + float clampedAmount = iconTransitionAmount > 0.5f ? 1.0f : 0.0f; + if (clampedAmount == fullTransitionAmount) { + iconState.noAnimations = (scrollingFast || expandingAnimated) && !forceInShelf; + iconState.useFullTransitionAmount = iconState.noAnimations + || (!ICON_ANMATIONS_WHILE_SCROLLING && fullTransitionAmount == 0.0f + && scrolling); + iconState.useLinearTransitionAmount = !ICON_ANMATIONS_WHILE_SCROLLING + && fullTransitionAmount == 0.0f && !mAmbientState.isExpansionChanging(); + iconState.translateContent = mMaxLayoutHeight - getTranslationY() + - getIntrinsicHeight() > 0; + } + if (!forceInShelf && (scrollingFast || (expandingAnimated + && iconState.useFullTransitionAmount && !ViewState.isAnimatingY(icon)))) { + iconState.cancelAnimations(icon); + iconState.useFullTransitionAmount = true; + iconState.noAnimations = true; + } + if (iconState.hasCustomTransformHeight()) { + iconState.useFullTransitionAmount = true; + } + if (iconState.isLastExpandIcon) { + iconState.translateContent = false; + } + float transitionAmount; + if (mAmbientState.isHiddenAtAll() && !view.isInShelf()) { + transitionAmount = mAmbientState.isFullyHidden() ? 1 : 0; + } else if (isLastChild || !USE_ANIMATIONS_WHEN_OPENING || iconState.useFullTransitionAmount - ? fullTransitionAmount - : transitionAmount; - iconState.clampedAppearAmount = clampedAmount; - float contentTransformationAmount = !row.isAboveShelf() && !row.showingPulsing() + || iconState.useLinearTransitionAmount) { + transitionAmount = iconTransitionAmount; + } else { + // We take the clamped position instead + transitionAmount = clampedAmount; + iconState.needsCannedAnimation = iconState.clampedAppearAmount != clampedAmount + && !mNoAnimationsInThisFrame; + } + iconState.iconAppearAmount = !USE_ANIMATIONS_WHEN_OPENING + || iconState.useFullTransitionAmount + ? fullTransitionAmount + : transitionAmount; + iconState.clampedAppearAmount = clampedAmount; + contentTransformationAmount = !view.isAboveShelf() && !view.showingPulsing() && (isLastChild || iconState.translateContent) - ? iconTransitionAmount - : 0.0f; - row.setContentTransformationAmount(contentTransformationAmount, isLastChild); - setIconTransformationAmount(row, transitionAmount, iconTransformDistance, - clampedAmount != transitionAmount, isLastChild); + ? iconTransitionAmount + : 0.0f; + setIconTransformationAmount(view, transitionAmount, iconTransformDistance, + clampedAmount != transitionAmount, isLastChild); + } + view.setContentTransformationAmount(contentTransformationAmount, isLastChild); } - private void setIconTransformationAmount(ExpandableNotificationRow row, + private void setIconTransformationAmount(ExpandableView view, float transitionAmount, float iconTransformDistance, boolean usingLinearInterpolation, boolean isLastChild) { - StatusBarIconView icon = row.getEntry().expandedIcon; + if (!(view instanceof ExpandableNotificationRow)) { + return; + } + ExpandableNotificationRow row = (ExpandableNotificationRow) view; + + StatusBarIconView icon = row.getShelfIcon(); NotificationIconContainer.IconState iconState = getIconState(icon); View rowIcon = row.getNotificationIcon(); @@ -950,6 +953,11 @@ public class NotificationShelf extends ActivatableNotificationView implements updateRelativeOffset(); } + @Override + public boolean needsClippingToShelf() { + return false; + } + public void onUiModeChanged() { updateBackgroundColors(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java index b03ba3c2a110..ea1bdd6a0ef6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java @@ -968,14 +968,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView return mCurrentBackgroundTint; } - public boolean isPinned() { - return false; - } - - public boolean isHeadsUpAnimatingAway() { - return false; - } - public boolean isHeadsUp() { return false; } 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 6d3f1267b38b..9a4e789a2e03 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 @@ -142,7 +142,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private LayoutListener mLayoutListener; private RowContentBindStage mRowContentBindStage; private int mIconTransformContentShift; - private int mIconTransformContentShiftNoIcon; private int mMaxHeadsUpHeightBeforeN; private int mMaxHeadsUpHeightBeforeP; private int mMaxHeadsUpHeight; @@ -312,10 +311,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private boolean mHeadsupDisappearRunning; private View mChildAfterViewWhenDismissed; private View mGroupParentWhenDismissed; - private float mContentTransformationAmount; private boolean mIconsVisible = true; private boolean mAboveShelf; - private boolean mIsLastChild; private Runnable mOnDismissRunnable; private boolean mIsLowPriority; private boolean mIsColorized; @@ -1504,18 +1501,19 @@ public class ExpandableNotificationRow extends ActivatableNotificationView updateIconVisibilities(); } - private void updateContentTransformation() { + @Override + protected void updateContentTransformation() { if (mExpandAnimationRunning) { return; } - float contentAlpha; - float translationY = -mContentTransformationAmount * mIconTransformContentShift; - if (mIsLastChild) { - contentAlpha = 1.0f - mContentTransformationAmount; - contentAlpha = Math.min(contentAlpha / 0.5f, 1.0f); - contentAlpha = Interpolators.ALPHA_OUT.getInterpolation(contentAlpha); - translationY *= 0.4f; - } else { + super.updateContentTransformation(); + } + + @Override + protected void applyContentTransformation(float contentAlpha, float translationY) { + super.applyContentTransformation(contentAlpha, translationY); + if (!mIsLastChild) { + // Don't fade views unless we're last contentAlpha = 1.0f; } for (NotificationContentView l : mLayouts) { @@ -1672,8 +1670,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView Resources res = getResources(); mIncreasedPaddingBetweenElements = res.getDimensionPixelSize( R.dimen.notification_divider_height_increased); - mIconTransformContentShiftNoIcon = res.getDimensionPixelSize( - R.dimen.notification_icon_transform_content_shift); mEnableNonGroupedNotificationExpand = res.getBoolean(R.bool.config_enableNonGroupedNotificationExpand); mShowGroupBackgroundWhenExpanded = @@ -2137,6 +2133,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } @Override + public StatusBarIconView getShelfIcon() { + return getEntry().expandedIcon; + } + + @Override protected boolean shouldClipToActualHeight() { return super.shouldClipToActualHeight() && !mExpandAnimationRunning; } @@ -2472,11 +2473,16 @@ public class ExpandableNotificationRow extends ActivatableNotificationView CachingIconView icon = notificationHeader.getIcon(); mIconTransformContentShift = getRelativeTopPadding(icon) + icon.getHeight(); } else { - mIconTransformContentShift = mIconTransformContentShiftNoIcon; + mIconTransformContentShift = mContentShift; } } @Override + protected float getContentTransformationShift() { + return mIconTransformContentShift; + } + + @Override public void notifyHeightChanged(boolean needsAnimation) { super.notifyHeightChanged(needsAnimation); getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java index e79d89f3a45c..a9f72ff9ea62 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.row; import android.animation.AnimatorListenerAdapter; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; @@ -28,6 +29,9 @@ import android.widget.FrameLayout; import androidx.annotation.Nullable; import com.android.systemui.Dumpable; +import com.android.systemui.Interpolators; +import com.android.systemui.R; +import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.notification.stack.ExpandableViewState; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; @@ -58,11 +62,26 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { private ViewGroup mTransientContainer; private boolean mInShelf; private boolean mTransformingInShelf; + protected float mContentTransformationAmount; + protected boolean mIsLastChild; + protected int mContentShift; private final ExpandableViewState mViewState; public ExpandableView(Context context, AttributeSet attrs) { super(context, attrs); mViewState = createExpandableViewState(); + initDimens(); + } + + private void initDimens() { + mContentShift = getResources().getDimensionPixelSize( + R.dimen.shelf_transform_content_shift); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + initDimens(); } @Override @@ -140,6 +159,22 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { } /** + * @return if this view needs to be clipped to the shelf + */ + public boolean needsClippingToShelf() { + return true; + } + + + public boolean isPinned() { + return false; + } + + public boolean isHeadsUpAnimatingAway() { + return false; + } + + /** * Sets the actual height of this notification. This is different than the laid out * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding. * @@ -578,7 +613,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { /** * @return whether the current view doesn't add height to the overall content. This means that - * if it is added to a list of items, it's content will still have the same height. + * if it is added to a list of items, its content will still have the same height. * An example is the notification shelf, that is always placed on top of another view. */ public boolean hasNoContentHeight() { @@ -596,6 +631,59 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { return mInShelf; } + public @Nullable StatusBarIconView getShelfIcon() { + return null; + } + + /** + * Set how much this notification is transformed into the shelf. + * + * @param contentTransformationAmount A value from 0 to 1 indicating how much we are transformed + * to the content away + * @param isLastChild is this the last child in the list. If true, then the transformation is + * different since its content fades out. + */ + public void setContentTransformationAmount(float contentTransformationAmount, + boolean isLastChild) { + boolean changeTransformation = isLastChild != mIsLastChild; + changeTransformation |= mContentTransformationAmount != contentTransformationAmount; + mIsLastChild = isLastChild; + mContentTransformationAmount = contentTransformationAmount; + if (changeTransformation) { + updateContentTransformation(); + } + } + + /** + * Update the content representation based on the amount we are transformed into the shelf. + */ + protected void updateContentTransformation() { + float translationY = -mContentTransformationAmount * getContentTransformationShift(); + float contentAlpha = 1.0f - mContentTransformationAmount; + contentAlpha = Math.min(contentAlpha / 0.5f, 1.0f); + contentAlpha = Interpolators.ALPHA_OUT.getInterpolation(contentAlpha); + if (mIsLastChild) { + translationY *= 0.4f; + } + applyContentTransformation(contentAlpha, translationY); + } + + /** + * @return how much the content shifts up when going into the shelf + */ + protected float getContentTransformationShift() { + return mContentShift; + } + + /** + * Apply the contentTransformation when going into the shelf. + * + * @param contentAlpha The alpha that should be applied + * @param translationY the translationY that should be applied + */ + protected void applyContentTransformation(float contentAlpha, float translationY) { + } + /** * @param transformingInShelf whether the view is currently transforming into the shelf in an * animated way diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java index eaa2eaf21927..82e5f0a3b130 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java @@ -49,6 +49,7 @@ public abstract class StackScrollerDecorView extends ExpandableView { public StackScrollerDecorView(Context context, AttributeSet attrs) { super(context, attrs); + setClipChildren(false); } @Override @@ -206,6 +207,11 @@ public abstract class StackScrollerDecorView extends ExpandableView { } @Override + public boolean needsClippingToShelf() { + return false; + } + + @Override public boolean hasOverlappingRendering() { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt index 0708f766738e..1b4f98f84c5b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt @@ -76,6 +76,19 @@ class PeopleHubView(context: Context, attrs: AttributeSet) : } } + override fun needsClippingToShelf(): Boolean { + return true + } + + override fun applyContentTransformation(contentAlpha: Float, translationY: Float) { + super.applyContentTransformation(contentAlpha, translationY) + for (i in 0 until contents.childCount) { + val view = contents.getChildAt(i) + view.alpha = contentAlpha + view.translationY = translationY + } + } + private inner class PersonDataListenerImpl(val avatarView: ImageView) : DataListener<PersonViewModel?> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java index ad3ff69eb5c8..deb5532ca0f2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java @@ -108,12 +108,26 @@ public class SectionHeaderView extends StackScrollerDecorView { mLabelView.setOnClickListener(listener); } + @Override + protected void applyContentTransformation(float contentAlpha, float translationY) { + super.applyContentTransformation(contentAlpha, translationY); + mLabelView.setAlpha(contentAlpha); + mLabelView.setTranslationY(translationY); + mClearAllButton.setAlpha(contentAlpha); + mClearAllButton.setTranslationY(translationY); + } + /** Fired when the user clicks on the "X" button on the far right of the header. */ void setOnClearAllClickListener(View.OnClickListener listener) { mOnClearClickListener = listener; mClearAllButton.setOnClickListener(listener); } + @Override + public boolean needsClippingToShelf() { + return true; + } + void setHeaderText(@StringRes int resId) { mLabelView.setText(resId); } |