summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mady Mellor <madym@google.com> 2016-05-24 20:59:49 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2016-05-24 20:59:50 +0000
commit31e49b0964cfba0b6b91e8ae67cbc04730098569 (patch)
treedc1b2f0e02515fe413fabed3e1a406bf08f396b7
parenta95568b84617e1c48e1eb6f505d58813f5227657 (diff)
parentb0a824687f56b6950338aad169d8d837f8ed657b (diff)
Merge "Children should have backgrounds" into nyc-dev
-rw-r--r--core/java/android/view/NotificationHeaderView.java55
-rw-r--r--core/res/res/values/dimens.xml3
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--packages/SystemUI/res/layout/notification_children_divider.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java250
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java191
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java6
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;
}
}
}