diff options
| author | 2016-05-24 20:59:49 +0000 | |
|---|---|---|
| committer | 2016-05-24 20:59:50 +0000 | |
| commit | 31e49b0964cfba0b6b91e8ae67cbc04730098569 (patch) | |
| tree | dc1b2f0e02515fe413fabed3e1a406bf08f396b7 | |
| parent | a95568b84617e1c48e1eb6f505d58813f5227657 (diff) | |
| parent | b0a824687f56b6950338aad169d8d837f8ed657b (diff) | |
Merge "Children should have backgrounds" into nyc-dev
17 files changed, 504 insertions, 171 deletions
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java index 37da8695a1ad..6e6baeadd45d 100644 --- a/core/java/android/view/NotificationHeaderView.java +++ b/core/java/android/view/NotificationHeaderView.java @@ -18,7 +18,11 @@ package android.view; import android.annotation.Nullable; import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Outline; import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; import android.widget.RemoteViews; @@ -47,6 +51,18 @@ public class NotificationHeaderView extends ViewGroup { private int mOriginalNotificationColor; private boolean mExpanded; private boolean mShowWorkBadgeAtEnd; + private Drawable mBackground; + private int mHeaderBackgroundHeight; + + ViewOutlineProvider mProvider = new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + if (mBackground != null) { + outline.setRect(0, 0, getWidth(), mHeaderBackgroundHeight); + outline.setAlpha(1f); + } + } + }; public NotificationHeaderView(Context context) { this(context, null); @@ -66,6 +82,8 @@ public class NotificationHeaderView extends ViewGroup { com.android.internal.R.dimen.notification_header_shrink_min_width); mContentEndMargin = getResources().getDimensionPixelSize( com.android.internal.R.dimen.notification_content_margin_end); + mHeaderBackgroundHeight = getResources().getDimensionPixelSize( + com.android.internal.R.dimen.notification_header_background_height); } @Override @@ -165,6 +183,43 @@ public class NotificationHeaderView extends ViewGroup { return new ViewGroup.MarginLayoutParams(getContext(), attrs); } + /** + * Set a {@link Drawable} to be displayed as a background on the header. + */ + public void setHeaderBackgroundDrawable(Drawable drawable) { + if (drawable != null) { + setWillNotDraw(false); + mBackground = drawable; + mBackground.setCallback(this); + setOutlineProvider(mProvider); + } else { + setWillNotDraw(true); + mBackground = null; + setOutlineProvider(null); + } + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + if (mBackground != null) { + mBackground.setBounds(0, 0, getWidth(), mHeaderBackgroundHeight); + mBackground.draw(canvas); + } + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mBackground; + } + + @Override + protected void drawableStateChanged() { + if (mBackground != null && mBackground.isStateful()) { + mBackground.setState(getDrawableState()); + } + } + private void updateTouchListener() { if (mExpandClickListener != null) { mTouchListener.bindTouchRects(); diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 573b066f0dfb..37fb8166e989 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -163,6 +163,9 @@ <!-- height of the content margin on the bottom --> <dimen name="notification_content_margin_bottom">16dp</dimen> + <!-- The height of the background for a notification header on a group --> + <dimen name="notification_header_background_height">45.5dp</dimen> + <!-- Height of a small notification in the status bar --> <dimen name="notification_min_height">92dp</dimen> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e99d57f0fa76..f2c3c4291be9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2436,6 +2436,7 @@ <java-symbol type="dimen" name="notification_content_picture_margin" /> <java-symbol type="dimen" name="notification_content_margin_top" /> <java-symbol type="dimen" name="notification_content_margin_bottom" /> + <java-symbol type="dimen" name="notification_header_background_height" /> <java-symbol type="string" name="importance_from_user" /> <java-symbol type="string" name="importance_from_person" /> diff --git a/packages/SystemUI/res/layout/notification_children_divider.xml b/packages/SystemUI/res/layout/notification_children_divider.xml index dad7cea3d989..76315b8e765f 100644 --- a/packages/SystemUI/res/layout/notification_children_divider.xml +++ b/packages/SystemUI/res/layout/notification_children_divider.xml @@ -20,4 +20,4 @@ android:id="@+id/notification_more_divider" android:layout_width="match_parent" android:layout_height="@dimen/notification_divider_height" - android:background="#61000000" /> + android:background="#FF616161" /> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index b8f576b0d366..cbb3c0ab52c7 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -248,6 +248,9 @@ <!-- The height of the divider between the individual notifications. --> <dimen name="notification_divider_height">0.5dp</dimen> + <!-- The height of a notification header --> + <dimen name="notification_header_height">53dp</dimen> + <!-- The height of the divider between the individual notifications when the notification wants it to be increased. This is currently the case for notification groups --> <dimen name="notification_divider_height_increased">6dp</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java index b6d8095d6c83..7a5e32227db1 100644 --- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java @@ -45,6 +45,7 @@ public class ExpandHelper implements Gefingerpoken { void setUserLockedChild(View v, boolean userLocked); void expansionStateChanged(boolean isExpanding); int getMaxExpandHeight(ExpandableView view); + void setExpansionCancelled(View view); } private static final String TAG = "ExpandHelper"; @@ -558,6 +559,8 @@ public class ExpandHelper implements Gefingerpoken { public void onAnimationEnd(Animator animation) { if (!mCancelled) { mCallback.setUserExpandedChild(scaledView, expand); + } else { + mCallback.setExpansionCancelled(scaledView); } mCallback.setUserLockedChild(scaledView, false); mScaleAnimation.removeListener(this); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index b4ce9cda3624..0a28331e03e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -22,7 +22,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.app.Notification; import android.content.Context; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.AnimationDrawable; @@ -31,6 +30,8 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.service.notification.StatusBarNotification; import android.util.AttributeSet; +import android.util.FloatProperty; +import android.util.Property; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.NotificationHeaderView; @@ -39,13 +40,11 @@ import android.view.ViewStub; import android.view.accessibility.AccessibilityEvent; import android.widget.Chronometer; import android.widget.ImageView; -import android.widget.RemoteViews; import com.android.internal.util.NotificationColorUtil; import com.android.systemui.R; import com.android.systemui.classifier.FalsingManager; import com.android.systemui.statusbar.notification.HybridNotificationView; -import com.android.systemui.statusbar.notification.NotificationViewWrapper; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.stack.NotificationChildrenContainer; @@ -65,6 +64,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private int mMaxHeadsUpHeight; private int mNotificationMinHeight; private int mNotificationMaxHeight; + private int mIncreasedPaddingBetweenElements; /** Does this row contain layouts that can adapt to row expansion */ private boolean mExpandable; @@ -97,7 +97,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { */ private boolean mOnKeyguard; - private AnimatorSet mTranslateAnim; + private Animator mTranslateAnim; private ArrayList<View> mTranslateableViews; private NotificationContentView mPublicLayout; private NotificationContentView mPrivateLayout; @@ -115,8 +115,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private String mAppName; private boolean mIsHeadsUp; private boolean mLastChronometerRunning = true; - private NotificationHeaderView mNotificationHeader; - private NotificationViewWrapper mNotificationHeaderWrapper; private ViewStub mChildrenContainerStub; private NotificationGroupManager mGroupManager; private boolean mChildrenExpanded; @@ -128,13 +126,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private boolean mIsPinned; private FalsingManager mFalsingManager; private HeadsUpManager mHeadsUpManager; - private NotificationHeaderUtil mHeaderUtil = new NotificationHeaderUtil(this); private boolean mJustClicked; private boolean mIconAnimationRunning; private boolean mShowNoBackground; private ExpandableNotificationRow mNotificationParent; private OnExpandClickListener mOnExpandClickListener; + private boolean mGroupExpansionChanging; + private OnClickListener mExpandClickListener = new OnClickListener() { @Override public void onClick(View v) { @@ -142,6 +141,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mGroupManager.toggleGroupExpansion(mStatusBarNotification); mOnExpandClickListener.onExpandClicked(mEntry, mGroupManager.isGroupExpanded(mStatusBarNotification)); + mGroupExpansionChanging = true; + updateBackgroundForGroupState(); } else { boolean nowExpanded; if (isPinned()) { @@ -160,6 +161,29 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private boolean mDismissed; private boolean mKeepInParent; private boolean mRemoved; + private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT = + new FloatProperty<ExpandableNotificationRow>("translate") { + @Override + public void setValue(ExpandableNotificationRow object, float value) { + object.setTranslation(value); + } + + @Override + public Float get(ExpandableNotificationRow object) { + return object.getTranslation(); + } + }; + + public boolean isGroupExpansionChanging() { + if (isChildInGroup()) { + return mNotificationParent.isGroupExpansionChanging(); + } + return mGroupExpansionChanging; + } + + public void setGroupExpansionChanging(boolean changing) { + mGroupExpansionChanging = changing; + } public NotificationContentView getPrivateLayout() { return mPrivateLayout; @@ -172,8 +196,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { public void setIconAnimationRunning(boolean running) { setIconAnimationRunning(running, mPublicLayout); setIconAnimationRunning(running, mPrivateLayout); - setIconAnimationRunningForChild(running, mNotificationHeader); if (mIsSummaryWithChildren) { + setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView()); List<ExpandableNotificationRow> notificationChildren = mChildrenContainer.getNotificationChildren(); for (int i = 0; i < notificationChildren.size(); i++) { @@ -235,7 +259,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { updateNotificationColor(); updateClearability(); if (mIsSummaryWithChildren) { - recreateNotificationHeader(); + mChildrenContainer.recreateNotificationHeader(mExpandClickListener, mEntry.notification); mChildrenContainer.onNotificationUpdated(); } if (mIconAnimationRunning) { @@ -329,9 +353,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { if (mChildrenContainer != null) { mChildrenContainer.removeNotification(row); } - if (!row.isRemoved()) { - mHeaderUtil.restoreNotificationHeader(row); - } onChildrenCountChanged(); row.setIsChildInGroup(false, null); } @@ -352,7 +373,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup; mNotificationParent = childInGroup ? parent : null; mPrivateLayout.setIsChildInGroup(childInGroup); - updateNoBackgroundState(); + updateBackgroundForGroupState(); + if (mNotificationParent != null) { + mNotificationParent.updateBackgroundForGroupState(); + } } @Override @@ -544,15 +568,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } public NotificationHeaderView getNotificationHeader() { - if (mNotificationHeader != null) { - return mNotificationHeader; + if (mIsSummaryWithChildren) { + return mChildrenContainer.getHeaderView(); } return mPrivateLayout.getNotificationHeader(); } private NotificationHeaderView getVisibleNotificationHeader() { - if (mNotificationHeader != null) { - return mNotificationHeader; + if (mIsSummaryWithChildren) { + return mChildrenContainer.getHeaderView(); } return getShowingLayout().getVisibleNotificationHeader(); } @@ -568,11 +592,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { public void reInflateViews() { initDimens(); if (mIsSummaryWithChildren) { - removeView(mNotificationHeader); - mNotificationHeader = null; - recreateNotificationHeader(); if (mChildrenContainer != null) { - mChildrenContainer.reInflateViews(); + mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification); } } if (mGuts != null) { @@ -646,9 +667,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { continue; } mChildrenContainer.removeNotification(row); - if (!row.isRemoved()) { - mHeaderUtil.restoreNotificationHeader(row); - } row.setIsChildInGroup(false, null); } onChildrenCountChanged(); @@ -709,6 +727,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mMaxHeadsUpHeightLegacy = getFontScaledHeight( R.dimen.notification_max_heads_up_height_legacy); mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height); + mIncreasedPaddingBetweenElements = getResources() + .getDimensionPixelSize(R.dimen.notification_divider_height_increased); } /** @@ -804,17 +824,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mTranslateableViews.remove(mGutsStub); } - private void setTranslationForOutline(float translationX) { - setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom()); - } - public void resetTranslation() { if (mTranslateableViews != null) { for (int i = 0; i < mTranslateableViews.size(); i++) { mTranslateableViews.get(i).setTranslationX(0); } - setTranslationForOutline(0); } + invalidateOutline(); if (mSettingsIconRow != null) { mSettingsIconRow.resetState(); } @@ -824,8 +840,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { if (mTranslateAnim != null) { mTranslateAnim.cancel(); } - mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget, - null /* updateListener */); + mTranslateAnim = getTranslateViewAnimator(leftTarget, null /* updateListener */); if (mTranslateAnim != null) { mTranslateAnim.start(); } @@ -843,7 +858,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mTranslateableViews.get(i).setTranslationX(translationX); } } - setTranslationForOutline(translationX); + invalidateOutline(); if (mSettingsIconRow != null) { mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth()); } @@ -867,48 +882,29 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { // No translation if guts are exposed. return null; } - AnimatorSet set = new AnimatorSet(); - if (mTranslateableViews != null) { - for (int i = 0; i < mTranslateableViews.size(); i++) { - final View animView = mTranslateableViews.get(i); - final ObjectAnimator translateAnim = ObjectAnimator.ofFloat( - animView, "translationX", leftTarget); - if (i == 0) { - translateAnim.addUpdateListener(new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - setTranslationForOutline((float) animation.getAnimatedValue()); - if (mSettingsIconRow != null) { - mSettingsIconRow.updateSettingsIcons( - (float) animation.getAnimatedValue(), getMeasuredWidth()); - } - } - }); - if (listener != null) { - translateAnim.addUpdateListener(listener); - } - translateAnim.addListener(new AnimatorListenerAdapter() { - boolean cancelled = false; + final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(this, TRANSLATE_CONTENT, + leftTarget); + if (listener != null) { + translateAnim.addUpdateListener(listener); + } + translateAnim.addListener(new AnimatorListenerAdapter() { + boolean cancelled = false; - @Override - public void onAnimationCancel(Animator anim) { - cancelled = true; - } + @Override + public void onAnimationCancel(Animator anim) { + cancelled = true; + } - @Override - public void onAnimationEnd(Animator anim) { - if (!cancelled && mSettingsIconRow != null && leftTarget == 0) { - mSettingsIconRow.resetState(); - mTranslateAnim = null; - } - } - }); + @Override + public void onAnimationEnd(Animator anim) { + if (!cancelled && mSettingsIconRow != null && leftTarget == 0) { + mSettingsIconRow.resetState(); + mTranslateAnim = null; } - set.play(translateAnim); } - } - mTranslateAnim = set; - return set; + }); + mTranslateAnim = translateAnim; + return translateAnim; } public float getSpaceForGear() { @@ -937,9 +933,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { if (mChildrenContainer != null) { mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE : INVISIBLE); - } - if (mNotificationHeader != null) { - mNotificationHeader.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE + mChildrenContainer.updateHeaderVisibility(!mShowingPublic && mIsSummaryWithChildren + ? VISIBLE : INVISIBLE); } // The limits might have changed if the view suddenly became a group or vice versa @@ -969,7 +964,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } if (mIsSummaryWithChildren) { mChildrenContainer.setDark(dark, fade, delay); - mNotificationHeaderWrapper.setDark(dark, fade, delay); } } @@ -1044,6 +1038,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mPrivateLayout.setUserExpanding(userLocked); if (mIsSummaryWithChildren) { mChildrenContainer.setUserLocked(userLocked); + if (userLocked) { + updateBackgroundForGroupState(); + } } } @@ -1123,30 +1120,28 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } } - private boolean isGroupExpanded() { + public boolean isGroupExpanded() { return mGroupManager.isGroupExpanded(mStatusBarNotification); } - /** - * @return whether this view has a header on the top of the content - */ - private boolean hasNotificationHeader() { - return mIsSummaryWithChildren; - } - private void onChildrenCountChanged() { mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS - && mChildrenContainer != null && mChildrenContainer.getChildCount() > 0; - if (mIsSummaryWithChildren) { - if (mNotificationHeader == null) { - recreateNotificationHeader(); - } + && mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0; + if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) { + mChildrenContainer.recreateNotificationHeader(mExpandClickListener, + mEntry.notification); } mPrivateLayout.updateExpandButtons(isExpandable()); updateChildrenHeaderAppearance(); updateChildrenVisibility(); } + public void updateChildrenHeaderAppearance() { + if (mChildrenContainer != null) { + mChildrenContainer.updateChildrenHeaderAppearance(); + } + } + /** * Check whether the view state is currently expanded. This is given by the system in {@link * #setSystemExpanded(boolean)} and can be overridden by user expansion or @@ -1251,8 +1246,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } private void animateShowingPublic(long delay, long duration) { - View[] privateViews = mIsSummaryWithChildren ? - new View[] {mChildrenContainer, mNotificationHeader} + View[] privateViews = mIsSummaryWithChildren + ? new View[] {mChildrenContainer} : new View[] {mPrivateLayout}; View[] publicViews = new View[] {mPublicLayout}; View[] hiddenChildren = mShowingPublic ? privateViews : publicViews; @@ -1302,9 +1297,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { public void setChildrenExpanded(boolean expanded, boolean animate) { mChildrenExpanded = expanded; - if (mNotificationHeader != null) { - mNotificationHeader.setExpanded(expanded); - } if (mChildrenContainer != null) { mChildrenContainer.setChildrenExpanded(expanded); } @@ -1349,6 +1341,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } @Override + public int getExtraBottomPadding() { + if (mIsSummaryWithChildren && isGroupExpanded()) { + return mIncreasedPaddingBetweenElements; + } + return 0; + } + + @Override public void setActualHeight(int height, boolean notifyListeners) { super.setActualHeight(height, notifyListeners); if (mGuts != null && mGuts.areGutsExposed()) { @@ -1406,33 +1406,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } } - private void recreateNotificationHeader() { - final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(), - getStatusBarNotification().getNotification()); - final RemoteViews header = builder.makeNotificationHeader(); - if (mNotificationHeader == null) { - mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this); - final View expandButton = mNotificationHeader.findViewById( - com.android.internal.R.id.expand_button); - expandButton.setVisibility(VISIBLE); - mNotificationHeader.setOnClickListener(mExpandClickListener); - mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(), - mNotificationHeader, this); - addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1); - mTranslateableViews.add(mNotificationHeader); - } else { - header.reapply(getContext(), mNotificationHeader); - mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification); - } - updateChildrenHeaderAppearance(); - } - - public void updateChildrenHeaderAppearance() { - if (mIsSummaryWithChildren) { - mHeaderUtil.updateChildrenHeaderAppearance(); - } - } - public boolean isMaxExpandHeightInitialized() { return mMaxExpandHeight != 0; } @@ -1451,19 +1424,50 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { @Override protected void updateBackgroundTint() { super.updateBackgroundTint(); - updateNoBackgroundState(); + updateBackgroundForGroupState(); if (mIsSummaryWithChildren) { List<ExpandableNotificationRow> notificationChildren = mChildrenContainer.getNotificationChildren(); for (int i = 0; i < notificationChildren.size(); i++) { ExpandableNotificationRow child = notificationChildren.get(i); - child.updateNoBackgroundState(); + child.updateBackgroundForGroupState(); } } } - private void updateNoBackgroundState() { - mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent); + /** + * Called when a group has finished animating from collapsed or expanded state. + */ + public void onFinishedExpansionChange() { + mGroupExpansionChanging = false; + updateBackgroundForGroupState(); + } + + /** + * Updates the parent and children backgrounds in a group based on the expansion state. + */ + public void updateBackgroundForGroupState() { + if (mIsSummaryWithChildren) { + // Only when the group has finished expanding do we hide its background. + mShowNoBackground = isGroupExpanded() && !isGroupExpansionChanging() && !isUserLocked(); + mChildrenContainer.updateHeaderForExpansion(mShowNoBackground); + List<ExpandableNotificationRow> children = mChildrenContainer.getNotificationChildren(); + for (int i = 0; i < children.size(); i++) { + children.get(i).updateBackgroundForGroupState(); + } + } else if (isChildInGroup()) { + final int childColor = getShowingLayout().getBackgroundColorForExpansionState(); + // Only show a background if the group is expanded OR if it is expanding / collapsing + // and has a custom background color + final boolean showBackground = isGroupExpanded() + || ((mNotificationParent.isGroupExpansionChanging() + || mNotificationParent.isUserLocked()) && childColor != 0); + mShowNoBackground = !showBackground; + } else { + // Only children or parents ever need no background. + mShowNoBackground = false; + } + updateOutline(); updateBackground(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java index f98e87d4848c..9d9f3b9640c4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java @@ -33,22 +33,25 @@ public abstract class ExpandableOutlineView extends ExpandableView { private boolean mCustomOutline; private float mOutlineAlpha = -1f; + ViewOutlineProvider mProvider = new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + int translation = (int) getTranslation(); + if (!mCustomOutline) { + outline.setRect(translation, + mClipTopAmount, + getWidth() + translation, + Math.max(getActualHeight(), mClipTopAmount)); + } else { + outline.setRect(mOutlineRect); + } + outline.setAlpha(mOutlineAlpha); + } + }; + public ExpandableOutlineView(Context context, AttributeSet attrs) { super(context, attrs); - setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - if (!mCustomOutline) { - outline.setRect(0, - mClipTopAmount, - getWidth(), - Math.max(getActualHeight(), mClipTopAmount)); - } else { - outline.setRect(mOutlineRect); - } - outline.setAlpha(mOutlineAlpha); - } - }); + setOutlineProvider(mProvider); } @Override @@ -87,17 +90,30 @@ public abstract class ExpandableOutlineView extends ExpandableView { @Override public int getOutlineTranslation() { - return mCustomOutline ? mOutlineRect.left : 0; + return mCustomOutline ? mOutlineRect.left : (int) getTranslation(); } - protected void setOutlineRect(float left, float top, float right, float bottom) { - setOutlineRect(true, left, top, right, bottom); + public void updateOutline() { + if (mCustomOutline) { + return; + } + boolean hasOutline = true; + if (isChildInGroup()) { + hasOutline = isGroupExpanded() && !isGroupExpansionChanging(); + } else if (isSummaryWithChildren()) { + hasOutline = !isGroupExpanded() || isGroupExpansionChanging(); + } + setOutlineProvider(hasOutline ? mProvider : null); } - protected void setOutlineRect(boolean clipToOutline, float left, float top, float right, - float bottom) { + public boolean isOutlineShowing() { + ViewOutlineProvider op = getOutlineProvider(); + return op != null; + } + + protected void setOutlineRect(float left, float top, float right, float bottom) { mCustomOutline = true; - setClipToOutline(clipToOutline); + setClipToOutline(true); mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 280663bf6c35..2c302ed1af4e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -323,7 +323,7 @@ public abstract class ExpandableView extends FrameLayout { if (top >= getActualHeight()) { top = getActualHeight() - 1; } - mClipRect.set(0, top, getWidth(), getActualHeight()); + mClipRect.set(0, top, getWidth(), getActualHeight() + getExtraBottomPadding()); setClipBounds(mClipRect); } else { setClipBounds(null); @@ -411,6 +411,28 @@ public abstract class ExpandableView extends FrameLayout { } /** + * @return padding used to alter how much of the view is clipped. + */ + public int getExtraBottomPadding() { + return 0; + } + + /** + * @return true if the group's expansion state is changing, false otherwise. + */ + public boolean isGroupExpansionChanging() { + return false; + } + + public boolean isGroupExpanded() { + return false; + } + + public boolean isChildInGroup() { + return false; + } + + /** * A listener notifying when {@link #getActualHeight} changes. */ public interface OnHeightChangedListener { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 5a8d4b357719..a0c13721644c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -71,7 +71,6 @@ public class NotificationContentView extends FrameLayout { private HybridGroupManager mHybridGroupManager; private int mClipTopAmount; private int mContentHeight; - private int mUnrestrictedContentHeight; private int mVisibleType = VISIBLE_TYPE_CONTRACTED; private boolean mDark; private boolean mAnimate; @@ -371,8 +370,7 @@ public class NotificationContentView extends FrameLayout { } public void setContentHeight(int contentHeight) { - mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());; - mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight()); + mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight()); selectLayout(mAnimate /* animate */, false /* force */); int minHeightHint = getMinContentHeightHint(); @@ -591,7 +589,21 @@ public class NotificationContentView extends FrameLayout { mContainingNotification.setContentBackground(customBackgroundColor, animate, this); } - private int getBackgroundColor(int visibleType) { + public int getVisibleType() { + return mVisibleType; + } + + public int getBackgroundColorForExpansionState() { + // When expanding or user locked we want the new type, when collapsing we want + // the original type + final int visibleType = (mContainingNotification.isGroupExpanded() + || mContainingNotification.isUserLocked()) + ? calculateVisibleType() + : getVisibleType(); + return getBackgroundColor(visibleType); + } + + public int getBackgroundColor(int visibleType) { NotificationViewWrapper currentVisibleWrapper = getVisibleWrapper(visibleType); int customBackgroundColor = 0; if (currentVisibleWrapper != null) { @@ -699,7 +711,7 @@ public class NotificationContentView extends FrameLayout { /** * @return one of the static enum types in this view, calculated form the current state */ - private int calculateVisibleType() { + public int calculateVisibleType() { if (mUserExpanding) { int height = !mIsChildInGroup || isGroupExpanded() || mContainingNotification.isExpanded(true /* allowOnKeyguard */) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java index 7575dc8157b6..7f95d48f36d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java @@ -90,7 +90,7 @@ public class NotificationHeaderUtil { private final ArrayList<HeaderProcessor> mComparators = new ArrayList<>(); private final HashSet<Integer> mDividers = new HashSet<>(); - NotificationHeaderUtil(ExpandableNotificationRow row) { + public NotificationHeaderUtil(ExpandableNotificationRow row) { mRow = row; // To hide the icons if they are the same and the color is the same mComparators.add(new HeaderProcessor(mRow, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 073994f8a5ce..f4873575c178 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -4335,6 +4335,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (expandView instanceof ExpandableNotificationRow) { row = (ExpandableNotificationRow) expandView; row.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */); + // Indicate that the group expansion is changing at this time -- this way the group + // and children backgrounds / divider animations will look correct. + row.setGroupExpansionChanging(true); } boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId) || !mShowLockscreenNotifications || mFalsingManager.shouldEnforceBouncer(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java index e919d5c48d3d..701a84454ce2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java @@ -16,21 +16,28 @@ package com.android.systemui.statusbar.stack; +import android.app.Notification; import android.content.Context; import android.content.res.Configuration; +import android.graphics.drawable.ColorDrawable; +import android.service.notification.StatusBarNotification; import android.util.AttributeSet; import android.view.LayoutInflater; +import android.view.NotificationHeaderView; import android.view.View; import android.view.ViewGroup; +import android.widget.RemoteViews; import android.widget.TextView; import com.android.systemui.R; import com.android.systemui.ViewInvertHelper; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.ExpandableNotificationRow; +import com.android.systemui.statusbar.NotificationHeaderUtil; import com.android.systemui.statusbar.notification.HybridGroupManager; import com.android.systemui.statusbar.notification.HybridNotificationView; import com.android.systemui.statusbar.notification.NotificationUtils; +import com.android.systemui.statusbar.notification.NotificationViewWrapper; import com.android.systemui.statusbar.phone.NotificationPanelView; import java.util.ArrayList; @@ -51,7 +58,7 @@ public class NotificationChildrenContainer extends ViewGroup { private int mChildPadding; private int mDividerHeight; private int mMaxNotificationHeight; - private int mNotificationHeaderHeight; + private int mNotificationHeaderMargin; private int mNotificatonTopPadding; private float mCollapsedBottompadding; private ViewInvertHelper mOverflowInvertHelper; @@ -63,6 +70,12 @@ public class NotificationChildrenContainer extends ViewGroup { private boolean mUserLocked; private int mActualHeight; private boolean mNeverAppliedGroupState; + private int mHeaderHeight; + + private NotificationHeaderView mNotificationHeader; + private NotificationViewWrapper mNotificationHeaderWrapper; + private NotificationHeaderUtil mHeaderUtil; + private ViewState mHeaderViewState; public NotificationChildrenContainer(Context context) { this(context, null); @@ -88,9 +101,10 @@ public class NotificationChildrenContainer extends ViewGroup { R.dimen.notification_children_padding); mDividerHeight = Math.max(1, getResources().getDimensionPixelSize( R.dimen.notification_divider_height)); + mHeaderHeight = getResources().getDimensionPixelSize(R.dimen.notification_header_height); mMaxNotificationHeight = getResources().getDimensionPixelSize( R.dimen.notification_max_height); - mNotificationHeaderHeight = getResources().getDimensionPixelSize( + mNotificationHeaderMargin = getResources().getDimensionPixelSize( com.android.internal.R.dimen.notification_content_margin_top); mNotificatonTopPadding = getResources().getDimensionPixelSize( R.dimen.notification_children_container_top_padding); @@ -112,6 +126,10 @@ public class NotificationChildrenContainer extends ViewGroup { mOverflowNumber.layout(getWidth() - mOverflowNumber.getMeasuredWidth(), 0, getWidth(), mOverflowNumber.getMeasuredHeight()); } + if (mNotificationHeader != null) { + mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(), + mNotificationHeader.getMeasuredHeight()); + } } @Override @@ -131,7 +149,7 @@ public class NotificationChildrenContainer extends ViewGroup { newHeightSpec); } int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY); - int height = mNotificationHeaderHeight + mNotificatonTopPadding; + int height = mNotificationHeaderMargin + mNotificatonTopPadding; int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED); int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */); int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1; @@ -155,6 +173,12 @@ public class NotificationChildrenContainer extends ViewGroup { if (heightMode != MeasureSpec.UNSPECIFIED) { height = Math.min(height, size); } + + if (mNotificationHeader != null) { + int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY); + mNotificationHeader.measure(widthMeasureSpec, headerHeightSpec); + } + setMeasuredDimension(width, height); } @@ -201,6 +225,41 @@ public class NotificationChildrenContainer extends ViewGroup { row.setSystemChildExpanded(false); row.setUserLocked(false); updateGroupOverflow(); + if (!row.isRemoved()) { + mHeaderUtil.restoreNotificationHeader(row); + } + } + + /** + * @return The number of notification children in the container. + */ + public int getNotificationChildCount() { + return mChildren.size(); + } + + public void recreateNotificationHeader(OnClickListener listener, StatusBarNotification notification) { + final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(), + mNotificationParent.getStatusBarNotification().getNotification()); + final RemoteViews header = builder.makeNotificationHeader(); + if (mNotificationHeader == null) { + mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this); + final View expandButton = mNotificationHeader.findViewById( + com.android.internal.R.id.expand_button); + expandButton.setVisibility(VISIBLE); + mNotificationHeader.setOnClickListener(listener); + mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(), + mNotificationHeader, mNotificationParent); + addView(mNotificationHeader, 0); + invalidate(); + } else { + header.reapply(getContext(), mNotificationHeader); + mNotificationHeaderWrapper.notifyContentUpdated(notification); + } + updateChildrenHeaderAppearance(); + } + + public void updateChildrenHeaderAppearance() { + mHeaderUtil.updateChildrenHeaderAppearance(); } public void updateGroupOverflow() { @@ -210,7 +269,7 @@ public class NotificationChildrenContainer extends ViewGroup { mOverflowNumber = mHybridGroupManager.bindOverflowNumber( mOverflowNumber, childCount - maxAllowedVisibleChildren); if (mOverflowInvertHelper == null) { - mOverflowInvertHelper= new ViewInvertHelper(mOverflowNumber, + mOverflowInvertHelper = new ViewInvertHelper(mOverflowNumber, NotificationPanelView.DOZE_ANIMATION_DURATION); } if (mGroupOverFlowState == null) { @@ -300,7 +359,7 @@ public class NotificationChildrenContainer extends ViewGroup { * in @param maxAllowedVisibleChildren */ private int getIntrinsicHeight(float maxAllowedVisibleChildren) { - int intrinsicHeight = mNotificationHeaderHeight; + int intrinsicHeight = mNotificationHeaderMargin; int visibleChildren = 0; int childCount = mChildren.size(); boolean firstChild = true; @@ -353,7 +412,7 @@ public class NotificationChildrenContainer extends ViewGroup { */ public void getState(StackScrollState resultState, StackViewState parentState) { int childCount = mChildren.size(); - int yPosition = mNotificationHeaderHeight; + int yPosition = mNotificationHeaderMargin; boolean firstChild = true; int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(); int lastVisibleIndex = maxAllowedVisibleChildren - 1; @@ -363,12 +422,16 @@ public class NotificationChildrenContainer extends ViewGroup { expandFactor = getGroupExpandFraction(); firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */); } + + boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging() + && mChildrenExpanded; + int parentHeight = parentState.height; for (int i = 0; i < childCount; i++) { ExpandableNotificationRow child = mChildren.get(i); if (!firstChild) { if (mUserLocked) { - yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight, - expandFactor); + yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight, + expandFactor); } else { yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding; } @@ -383,11 +446,28 @@ public class NotificationChildrenContainer extends ViewGroup { } firstChild = false; } + StackViewState childState = resultState.getViewStateForView(child); int intrinsicHeight = child.getIntrinsicHeight(); + if (childrenExpanded) { + // When a group is expanded and moving into bottom stack, the bottom visible child + // adjusts its height to move into it. Children after it are hidden. + if (updateChildStateForExpandedGroup(child, parentHeight, childState, yPosition)) { + // Clipping might be deactivated if the view is transforming, however, clipping + // the child into the bottom stack should take precedent over this. + childState.isBottomClipped = true; + } + } else { + childState.hidden = false; + childState.height = intrinsicHeight; + childState.isBottomClipped = false; + } childState.yTranslation = yPosition; - childState.zTranslation = 0; - childState.height = intrinsicHeight; + // When the group is expanded, the children cast the shadows rather than the parent + // so use the parent's elevation here. + childState.zTranslation = childrenExpanded + ? mNotificationParent.getTranslationZ() + : 0; childState.dimmed = parentState.dimmed; childState.dark = parentState.dark; childState.hideSensitive = parentState.hideSensitive; @@ -422,10 +502,44 @@ public class NotificationChildrenContainer extends ViewGroup { mGroupOverFlowState.alpha = mirrorView.getAlpha(); } } else { - mGroupOverFlowState.yTranslation += mNotificationHeaderHeight; + mGroupOverFlowState.yTranslation += mNotificationHeaderMargin; mGroupOverFlowState.alpha = 0.0f; } } + if (mNotificationHeader != null) { + if (mHeaderViewState == null) { + mHeaderViewState = new ViewState(); + } + mHeaderViewState.initFrom(mNotificationHeader); + mHeaderViewState.zTranslation = childrenExpanded + ? mNotificationParent.getTranslationZ() + : 0; + } + } + + /** + * When moving into the bottom stack, the bottom visible child in an expanded group adjusts its + * height, children in the group after this are gone. + * + * @param child the child who's height to adjust. + * @param parentHeight the height of the parent. + * @param childState the state to update. + * @param yPosition the yPosition of the view. + * @return true if children after this one should be hidden. + */ + private boolean updateChildStateForExpandedGroup(ExpandableNotificationRow child, + int parentHeight, StackViewState childState, int yPosition) { + final int top = yPosition + child.getClipTopAmount(); + final int intrinsicHeight = child.getIntrinsicHeight(); + final int bottom = top + intrinsicHeight; + int newHeight = intrinsicHeight; + if (bottom >= parentHeight) { + // Child is either clipped or gone + newHeight = Math.max((parentHeight - top), 0); + } + childState.hidden = newHeight == 0; + childState.height = newHeight; + return childState.height != intrinsicHeight && !childState.hidden; } private int getMaxAllowedVisibleChildren() { @@ -450,6 +564,8 @@ public class NotificationChildrenContainer extends ViewGroup { if (mUserLocked) { expandFraction = getGroupExpandFraction(); } + final boolean dividersVisible = mUserLocked + || mNotificationParent.isGroupExpansionChanging(); for (int i = 0; i < childCount; i++) { ExpandableNotificationRow child = mChildren.get(i); StackViewState viewState = state.getViewStateForView(child); @@ -464,6 +580,7 @@ public class NotificationChildrenContainer extends ViewGroup { alpha = NotificationUtils.interpolate(0, 0.5f, Math.min(viewState.alpha, expandFraction)); } + tmpState.hidden = !dividersVisible; tmpState.alpha = alpha; state.applyViewState(divider, tmpState); // There is no fake shadow to be drawn on the children @@ -473,6 +590,9 @@ public class NotificationChildrenContainer extends ViewGroup { state.applyViewState(mOverflowNumber, mGroupOverFlowState); mNeverAppliedGroupState = false; } + if (mNotificationHeader != null) { + state.applyViewState(mNotificationHeader, mHeaderViewState); + } } /** @@ -491,6 +611,8 @@ public class NotificationChildrenContainer extends ViewGroup { int childCount = mChildren.size(); ViewState tmpState = new ViewState(); float expandFraction = getGroupExpandFraction(); + final boolean dividersVisible = mUserLocked + || mNotificationParent.isGroupExpansionChanging(); for (int i = childCount - 1; i >= 0; i--) { ExpandableNotificationRow child = mChildren.get(i); StackViewState viewState = state.getViewStateForView(child); @@ -505,6 +627,7 @@ public class NotificationChildrenContainer extends ViewGroup { alpha = NotificationUtils.interpolate(0, 0.5f, Math.min(viewState.alpha, expandFraction)); } + tmpState.hidden = !dividersVisible; tmpState.alpha = alpha; stateAnimator.startViewAnimations(divider, tmpState, baseDelay, duration); // There is no fake shadow to be drawn on the children @@ -521,6 +644,9 @@ public class NotificationChildrenContainer extends ViewGroup { stateAnimator.startViewAnimations(mOverflowNumber, mGroupOverFlowState, baseDelay, duration); } + if (mNotificationHeader != null) { + state.applyViewState(mNotificationHeader, mHeaderViewState); + } } public ExpandableNotificationRow getViewAtPosition(float y) { @@ -541,14 +667,45 @@ public class NotificationChildrenContainer extends ViewGroup { public void setChildrenExpanded(boolean childrenExpanded) { mChildrenExpanded = childrenExpanded; updateExpansionStates(); + if (mNotificationHeader != null) { + mNotificationHeader.setExpanded(childrenExpanded); + } } public void setNotificationParent(ExpandableNotificationRow parent) { mNotificationParent = parent; + mHeaderUtil = new NotificationHeaderUtil(mNotificationParent); + } + + public NotificationHeaderView getHeaderView() { + return mNotificationHeader; + } + + public void updateHeaderVisibility(int visiblity) { + if (mNotificationHeader != null) { + mNotificationHeader.setVisibility(visiblity); + } + } + + /** + * Called when a groups expansion changes to adjust the background of the header view. + * + * @param expanded whether the group is expanded. + */ + public void updateHeaderForExpansion(boolean expanded) { + if (mNotificationHeader != null) { + if (expanded) { + ColorDrawable cd = new ColorDrawable(); + cd.setColor(mNotificationParent.calculateBgColor()); + mNotificationHeader.setHeaderBackgroundDrawable(cd); + } else { + mNotificationHeader.setHeaderBackgroundDrawable(null); + } + } } public int getMaxContentHeight() { - int maxContentHeight = mNotificationHeaderHeight + mNotificatonTopPadding; + int maxContentHeight = mNotificationHeaderMargin + mNotificatonTopPadding; int visibleChildren = 0; int childCount = mChildren.size(); for (int i = 0; i < childCount; i++) { @@ -601,7 +758,7 @@ public class NotificationChildrenContainer extends ViewGroup { } private int getVisibleChildrenExpandHeight() { - int intrinsicHeight = mNotificationHeaderHeight + mNotificatonTopPadding + mDividerHeight; + int intrinsicHeight = mNotificationHeaderMargin + mNotificatonTopPadding + mDividerHeight; int visibleChildren = 0; int childCount = mChildren.size(); int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */); @@ -628,7 +785,7 @@ public class NotificationChildrenContainer extends ViewGroup { } private int getMinHeight(int maxAllowedVisibleChildren) { - int minExpandHeight = mNotificationHeaderHeight; + int minExpandHeight = mNotificationHeaderMargin; int visibleChildren = 0; boolean firstChild = true; int childCount = mChildren.size(); @@ -653,9 +810,13 @@ public class NotificationChildrenContainer extends ViewGroup { if (mOverflowNumber != null) { mOverflowInvertHelper.setInverted(dark, fade, delay); } + mNotificationHeaderWrapper.setDark(dark, fade, delay); } - public void reInflateViews() { + public void reInflateViews(OnClickListener listener, StatusBarNotification notification) { + removeView(mNotificationHeader); + mNotificationHeader = null; + recreateNotificationHeader(listener, notification); initDimens(); for (int i = 0; i < mDividers.size(); i++) { View prevDivider = mDividers.get(i); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 5976020bbf9e..3ce98662dae8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -733,6 +733,7 @@ public class NotificationStackScrollLayout extends ViewGroup mQsContainer = qsContainer; } + @Override public void onChildDismissed(View v) { ExpandableNotificationRow row = (ExpandableNotificationRow) v; if (!row.isDismissed()) { @@ -820,6 +821,7 @@ public class NotificationStackScrollLayout extends ViewGroup return true; // Don't fade out the notification } + @Override public void onBeginDrag(View v) { mFalsingManager.onNotificatonStartDismissing(); setSwipingInProgress(true); @@ -848,6 +850,7 @@ public class NotificationStackScrollLayout extends ViewGroup return false; } + @Override public void onDragCancelled(View v) { mFalsingManager.onNotificatonStopDismissing(); setSwipingInProgress(false); @@ -906,11 +909,13 @@ public class NotificationStackScrollLayout extends ViewGroup return closestChild; } + @Override public ExpandableView getChildAtRawPosition(float touchX, float touchY) { getLocationOnScreen(mTempInt2); return getChildAtPosition(touchX - mTempInt2[0], touchY - mTempInt2[1]); } + @Override public ExpandableView getChildAtPosition(float touchX, float touchY) { // find the view under the pointer, accounting for GONE views final int count = getChildCount(); @@ -947,12 +952,14 @@ public class NotificationStackScrollLayout extends ViewGroup return null; } + @Override public boolean canChildBeExpanded(View v) { return v instanceof ExpandableNotificationRow && ((ExpandableNotificationRow) v).isExpandable() && (mIsExpanded || !((ExpandableNotificationRow) v).isPinned()); } + @Override public void setUserExpandedChild(View v, boolean userExpanded) { if (v instanceof ExpandableNotificationRow) { ((ExpandableNotificationRow) v).setUserExpanded(userExpanded, @@ -960,6 +967,14 @@ public class NotificationStackScrollLayout extends ViewGroup } } + @Override + public void setExpansionCancelled(View v) { + if (v instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) v).setGroupExpansionChanging(false); + } + } + + @Override public void setUserLockedChild(View v, boolean userLocked) { if (v instanceof ExpandableNotificationRow) { ((ExpandableNotificationRow) v).setUserLocked(userLocked); @@ -1070,6 +1085,7 @@ public class NotificationStackScrollLayout extends ViewGroup return mScrollingEnabled; } + @Override public boolean canChildBeDismissed(View v) { return StackScrollAlgorithm.canChildBeDismissed(v); } @@ -1927,7 +1943,8 @@ public class NotificationStackScrollLayout extends ViewGroup // we're ending up at the same location as we are now, lets just skip the animation bottom = finalBottom; } else { - bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()); + bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight() + - lastView.getExtraBottomPadding()); bottom = Math.min(bottom, getHeight()); } } else { @@ -3153,8 +3170,9 @@ public class NotificationStackScrollLayout extends ViewGroup expandableView.setFakeShadowIntensity(0.0f, 0.0f, 0, 0); } else { float yLocation = previous.getTranslationY() + previous.getActualHeight() - - expandableView.getTranslationY(); - expandableView.setFakeShadowIntensity(diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD, + expandableView.getTranslationY() - previous.getExtraBottomPadding(); + expandableView.setFakeShadowIntensity( + diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD, previous.getOutlineAlpha(), (int) yLocation, previous.getOutlineTranslation()); } @@ -3525,6 +3543,12 @@ public class NotificationStackScrollLayout extends ViewGroup if (!mGroupExpandedForMeasure) { onHeightChanged(changedRow, false /* needsAnimation */); } + runAfterAnimationFinished(new Runnable() { + @Override + public void run() { + changedRow.onFinishedExpansionChange(); + } + }); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java index 1ccc9083f72c..d6c550678174 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java @@ -173,6 +173,9 @@ public class StackScrollState { } if (view instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) view; + if (state.isBottomClipped) { + row.setClipToActualHeight(true); + } row.applyChildrenState(this); } return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java index 6f451ffa381a..0f94227c6184 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -223,7 +223,7 @@ public class StackStateAnimator { startViewAnimations(child, viewState, delay, duration); // start height animation - if (heightChanging && child.getActualHeight() != 0) { + if (heightChanging) { startHeightAnimation(child, viewState, duration, delay); } @@ -270,7 +270,8 @@ public class StackStateAnimator { public void startViewAnimations(View child, ViewState viewState, long delay, long duration) { boolean wasVisible = child.getVisibility() == View.VISIBLE; final float alpha = viewState.alpha; - if (!wasVisible && alpha != 0 && !viewState.gone && !viewState.hidden) { + if (!wasVisible && (alpha != 0 || child.getAlpha() != 0) + && !viewState.gone && !viewState.hidden) { child.setVisibility(View.VISIBLE); } boolean yTranslationChanging = child.getTranslationY() != viewState.yTranslation; @@ -477,11 +478,27 @@ public class StackStateAnimator { animator.addListener(getGlobalAnimationFinishedListener()); // remove the tag when the animation is finished animator.addListener(new AnimatorListenerAdapter() { + boolean mWasCancelled; + @Override public void onAnimationEnd(Animator animation) { child.setTag(TAG_ANIMATOR_HEIGHT, null); child.setTag(TAG_START_HEIGHT, null); child.setTag(TAG_END_HEIGHT, null); + if (!mWasCancelled && child instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) child).setGroupExpansionChanging( + false /* isExpansionChanging */); + } + } + + @Override + public void onAnimationStart(Animator animation) { + mWasCancelled = false; + } + + @Override + public void onAnimationCancel(Animator animation) { + mWasCancelled = true; } }); startAnimator(animator); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java index 1114e0359d6d..ecdee4eaecba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java @@ -57,6 +57,11 @@ public class StackViewState extends ViewState { */ public int location; + /** + * Whether a child in a group is being clipped at the bottom. + */ + public boolean isBottomClipped; + @Override public void copyFrom(ViewState viewState) { super.copyFrom(viewState); @@ -71,6 +76,7 @@ public class StackViewState extends ViewState { clipTopAmount = svs.clipTopAmount; notGoneIndex = svs.notGoneIndex; location = svs.location; + isBottomClipped = svs.isBottomClipped; } } } |