Changed the appearance of notification bundles
Children now show up as one line notifications even
if the summary is not expanded. The childrenContainer
shows a summary if there are some which don't fit
in there currently.
Bug: 24866646
Change-Id: I0cfae9342722c9f8941f51704618190cfe4e76b4
diff --git a/packages/SystemUI/res/layout/hybrid_notification.xml b/packages/SystemUI/res/layout/hybrid_notification.xml
new file mode 100644
index 0000000..9e64d2c
--- /dev/null
+++ b/packages/SystemUI/res/layout/hybrid_notification.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<com.android.systemui.statusbar.notification.HybridNotificationView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/notification_max_height">
+ <TextView
+ android:id="@+id/notification_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:singleLine="true"
+ android:textAppearance="@*android:style/TextAppearance.Material.Notification.Title"
+ android:paddingEnd="4dp"
+ />
+ <TextView
+ android:id="@+id/notification_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textAppearance="@*android:style/TextAppearance.Material.Notification"
+ android:singleLine="true"
+ />
+</com.android.systemui.statusbar.notification.HybridNotificationView>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9fd82ed..c413524 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -36,6 +36,18 @@
<!-- The font size for the clock -->
<dimen name="status_bar_clock_size">14sp</dimen>
+ <!-- The margin on the start of the content view -->
+ <dimen name="notification_content_margin_start">16dp</dimen>
+
+ <!-- The maximum size of the title when in single line mode -->
+ <dimen name="notification_maximum_title_length">150sp</dimen>
+
+ <!-- The margin on the end of the content view -->
+ <dimen name="notification_content_margin_end">8dp</dimen>
+
+ <!-- Height of a single line notification in the status bar -->
+ <dimen name="notification_single_line_height">32sp</dimen>
+
<!-- Height of a small notification in the status bar -->
<dimen name="notification_min_height">64dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 844bab3..d5f9557e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1026,6 +1026,9 @@
<!-- VolumeUI restoration notification: text -->
<string name="volumeui_notification_text">Touch to restore the original.</string>
+ <!-- Describes the way 2 names are concatenated. An example would be ", " to produce "Peter Muller, Paul Curry". Please also include a space here if it's appropriate in the language and if it's a RTL language include it on the left. [CHAR LIMIT=3] -->
+ <string name="group_summary_concadenation">, </string>
+
<!-- Toast shown when user unlocks screen and managed profile activity is in the foreground -->
<string name="managed_profile_foreground_toast">You\'re using your work profile</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index ec22b9f..1e038c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1929,27 +1929,29 @@
for (int i = 0; i < N; i++) {
NotificationData.Entry entry = activeNotifications.get(i);
if (onKeyguard) {
- entry.row.setExpansionDisabled(true);
+ entry.row.setOnKeyguard(true);
} else {
- entry.row.setExpansionDisabled(false);
- if (!entry.row.isUserLocked()) {
- boolean top = (i == 0);
- entry.row.setSystemExpanded(top);
- }
+ entry.row.setOnKeyguard(false);
+ boolean top = (i == 0);
+ entry.row.setSystemExpanded(top);
}
- boolean isInvisibleChild = !mGroupManager.isVisible(entry.notification);
+ boolean childNotification = mGroupManager.isChildInGroupWithSummary(entry.notification);
+ boolean childWithVisibleSummary = childNotification
+ && mGroupManager.getGroupSummary(entry.notification).getVisibility()
+ == View.VISIBLE;
boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
if ((isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
(onKeyguard && (visibleNotifications >= maxKeyguardNotifications
- || !showOnKeyguard || isInvisibleChild))) {
+ && !childWithVisibleSummary
+ || !showOnKeyguard))) {
entry.row.setVisibility(View.GONE);
- if (onKeyguard && showOnKeyguard && !isInvisibleChild) {
+ if (onKeyguard && showOnKeyguard && !childNotification) {
mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
}
} else {
boolean wasGone = entry.row.getVisibility() == View.GONE;
entry.row.setVisibility(View.VISIBLE);
- if (!isInvisibleChild) {
+ if (!childNotification) {
if (wasGone) {
// notify the scroller of a child addition
mStackScroller.generateAddAnimation(entry.row, true /* fromMoreCard */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index b8df139..7078f33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -70,9 +70,9 @@
private boolean mIsSystemExpanded;
/**
- * Whether the notification expansion is disabled. This is the case on Keyguard.
+ * Whether the notification is on the keyguard and the expansion is disabled.
*/
- private boolean mExpansionDisabled;
+ private boolean mOnKeyguard;
private NotificationContentView mPublicLayout;
private NotificationContentView mPrivateLayout;
@@ -162,6 +162,7 @@
private void setStatusBarNotification(StatusBarNotification statusBarNotification) {
mStatusBarNotification = statusBarNotification;
+ mPrivateLayout.setStatusBarNotification(statusBarNotification);
updateVetoButton();
onChildrenCountChanged();
}
@@ -185,6 +186,7 @@
public void setGroupManager(NotificationGroupManager groupManager) {
mGroupManager = groupManager;
+ mPrivateLayout.setGroupManager(groupManager);
}
public void addChildNotification(ExpandableNotificationRow row) {
@@ -225,6 +227,7 @@
public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {
mChildInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
mShowNoBackground = mChildInGroup && hasSameBgColor(parent);
+ mPrivateLayout.setIsChildInGroup(mShowNoBackground);
updateBackground();
}
@@ -265,34 +268,34 @@
}
public void getChildrenStates(StackScrollState resultState) {
- if (mChildrenExpanded) {
+ if (mIsSummaryWithChildren) {
StackViewState parentState = resultState.getViewStateForView(this);
mChildrenContainer.getState(resultState, parentState);
}
}
public void applyChildrenState(StackScrollState state) {
- if (mChildrenExpanded) {
+ if (mIsSummaryWithChildren) {
mChildrenContainer.applyState(state);
}
}
public void prepareExpansionChanged(StackScrollState state) {
- if (mChildrenExpanded) {
+ if (mIsSummaryWithChildren) {
mChildrenContainer.prepareExpansionChanged(state);
}
}
public void startChildAnimation(StackScrollState finalState,
StackStateAnimator stateAnimator, boolean withDelays, long delay, long duration) {
- if (mChildrenExpanded) {
+ if (mIsSummaryWithChildren) {
mChildrenContainer.startAnimationToState(finalState, stateAnimator, withDelays, delay,
duration);
}
}
public ExpandableNotificationRow getViewAtPosition(float y) {
- if (!mChildrenExpanded) {
+ if (!mIsSummaryWithChildren || !mChildrenExpanded) {
return this;
} else {
ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
@@ -416,7 +419,7 @@
mSensitive = false;
mShowingPublicInitialized = false;
mIsSystemExpanded = false;
- mExpansionDisabled = false;
+ mOnKeyguard = false;
mPublicLayout.reset(mIsHeadsUp);
mPrivateLayout.reset(mIsHeadsUp);
resetHeight();
@@ -580,16 +583,19 @@
mIsSystemExpanded = expand;
notifyHeightChanged(false /* needsAnimation */);
logExpansionEvent(false, wasExpanded);
+ if (mChildrenContainer != null) {
+ mChildrenContainer.updateGroupOverflow();
+ }
}
}
/**
- * @param expansionDisabled whether to prevent notification expansion
+ * @param onKeyguard whether to prevent notification expansion
*/
- public void setExpansionDisabled(boolean expansionDisabled) {
- if (expansionDisabled != mExpansionDisabled) {
+ public void setOnKeyguard(boolean onKeyguard) {
+ if (onKeyguard != mOnKeyguard) {
final boolean wasExpanded = isExpanded();
- mExpansionDisabled = expansionDisabled;
+ mOnKeyguard = onKeyguard;
logExpansionEvent(false, wasExpanded);
if (wasExpanded != isExpanded()) {
notifyHeightChanged(false /* needsAnimation */);
@@ -622,23 +628,22 @@
return getActualHeight();
}
boolean inExpansionState = isExpanded();
- int maxContentHeight;
if (mSensitive && mHideSensitiveForIntrinsicHeight) {
return mRowMinHeight;
+ } else if (mIsSummaryWithChildren && !mOnKeyguard) {
+ return mChildrenContainer.getIntrinsicHeight()
+ + mNotificationHeader.getHeight();
} else if (mIsHeadsUp) {
if (inExpansionState) {
- maxContentHeight = Math.max(mMaxExpandHeight, mHeadsUpHeight);
+ return Math.max(mMaxExpandHeight, mHeadsUpHeight);
} else {
- maxContentHeight = Math.max(mRowMinHeight, mHeadsUpHeight);
+ return Math.max(mRowMinHeight, mHeadsUpHeight);
}
- } else if ((!inExpansionState && !mChildrenExpanded)) {
- maxContentHeight = mRowMinHeight;
- } else if (mChildrenExpanded) {
- maxContentHeight = mChildrenContainer.getIntrinsicHeight();
+ } else if (!inExpansionState || (mChildInGroup && !isGroupExpanded())) {
+ return getMinHeight();
} else {
- maxContentHeight = getMaxExpandHeight();
+ return getMaxExpandHeight();
}
- return maxContentHeight;
}
private boolean isGroupExpanded() {
@@ -670,8 +675,8 @@
*
* @return whether the view state is currently expanded.
*/
- private boolean isExpanded() {
- return !mExpansionDisabled
+ public boolean isExpanded() {
+ return !mOnKeyguard
&& (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
|| isUserExpanded());
}
@@ -778,6 +783,9 @@
public void setChildrenExpanded(boolean expanded, boolean animate) {
mChildrenExpanded = expanded;
+ if (mChildrenContainer != null) {
+ mChildrenContainer.setChildrenExpanded(expanded);
+ }
}
public void updateNotificationHeader() {
@@ -844,12 +852,20 @@
@Override
public int getMaxContentHeight() {
+ if (mIsSummaryWithChildren && !mShowingPublic) {
+ return mChildrenContainer.getMaxContentHeight()
+ + mNotificationHeader.getHeight();
+ }
NotificationContentView showingLayout = getShowingLayout();
return showingLayout.getMaxHeight();
}
@Override
public int getMinHeight() {
+ if (mIsSummaryWithChildren && !mOnKeyguard) {
+ return mChildrenContainer.getMinHeight()
+ + mNotificationHeader.getHeight();
+ }
NotificationContentView showingLayout = getShowingLayout();
return showingLayout.getMinHeight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 0e32b62..5aedaf1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -22,6 +22,7 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -32,6 +33,9 @@
import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.HybridNotificationView;
+import com.android.systemui.statusbar.notification.HybridNotificationViewManager;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
/**
* A frame layout containing the actual payload of the notification, including the contracted,
@@ -44,8 +48,10 @@
private static final int VISIBLE_TYPE_CONTRACTED = 0;
private static final int VISIBLE_TYPE_EXPANDED = 1;
private static final int VISIBLE_TYPE_HEADSUP = 2;
+ private static final int VISIBLE_TYPE_SINGLELINE = 3;
private final Rect mClipBounds = new Rect();
+ private final int mSingleLineHeight;
private final int mSmallHeight;
private final int mHeadsUpHeight;
private final int mRoundRectRadius;
@@ -55,10 +61,12 @@
private View mContractedChild;
private View mExpandedChild;
private View mHeadsUpChild;
+ private HybridNotificationView mSingleLineView;
private NotificationViewWrapper mContractedWrapper;
private NotificationViewWrapper mExpandedWrapper;
private NotificationViewWrapper mHeadsUpWrapper;
+ private HybridNotificationViewManager mHybridViewManager;
private int mClipTopAmount;
private int mContentHeight;
private int mUnrestrictedContentHeight;
@@ -68,6 +76,8 @@
private boolean mAnimate;
private boolean mIsHeadsUp;
private boolean mShowingLegacyBackground;
+ private boolean mIsChildInGroup;
+ private StatusBarNotification mStatusBarNotification;
private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
= new ViewTreeObserver.OnPreDrawListener() {
@@ -86,10 +96,14 @@
mRoundRectRadius);
}
};
+ private NotificationGroupManager mGroupManager;
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mHybridViewManager = new HybridNotificationViewManager(getContext(), this);
mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
+ mSingleLineHeight = getResources().getDimensionPixelSize(
+ R.dimen.notification_single_line_height);
mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
mHeadsUpHeight = getResources().getDimensionPixelSize(R.dimen.notification_mid_height);
mRoundRectRadius = getResources().getDimensionPixelSize(
@@ -140,6 +154,12 @@
MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST));
maxChildHeight = Math.max(maxChildHeight, mHeadsUpChild.getMeasuredHeight());
}
+ if (mSingleLineView != null) {
+ int size = Math.min(maxSize, mSingleLineHeight);
+ mSingleLineView.measure(widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY));
+ maxChildHeight = Math.max(maxChildHeight, mSingleLineView.getMeasuredHeight());
+ }
int ownHeight = Math.min(maxChildHeight, maxSize);
int width = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width, ownHeight);
@@ -271,7 +291,15 @@
}
public int getMinHeight() {
- return mSmallHeight;
+ if (mIsChildInGroup && !isGroupExpanded()) {
+ return mSingleLineHeight;
+ } else {
+ return mSmallHeight;
+ }
+ }
+
+ private boolean isGroupExpanded() {
+ return mGroupManager.isGroupExpanded(mStatusBarNotification);
}
public void setClipTopAmount(int clipTopAmount) {
@@ -313,6 +341,7 @@
if (visibleType != mVisibleType || force) {
if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
|| (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
+ || (visibleType == VISIBLE_TYPE_SINGLELINE && mSingleLineView != null)
|| visibleType == VISIBLE_TYPE_CONTRACTED)) {
runSwitchAnimation(visibleType);
} else {
@@ -339,6 +368,12 @@
mHeadsUpChild.setAlpha(headsUpVisible ? 1f : 0f);
mHeadsUpChild.setLayerType(LAYER_TYPE_NONE, null);
}
+ if (mSingleLineView != null) {
+ boolean singleLineVisible = visibleType == VISIBLE_TYPE_SINGLELINE;
+ mSingleLineView.setVisibility(singleLineVisible ? View.VISIBLE : View.INVISIBLE);
+ mSingleLineView.setAlpha(singleLineVisible ? 1f : 0f);
+ mSingleLineView.setLayerType(LAYER_TYPE_NONE, null);
+ }
setLayerType(LAYER_TYPE_NONE, null);
updateRoundRectClipping();
}
@@ -379,6 +414,8 @@
return mExpandedChild;
case VISIBLE_TYPE_HEADSUP:
return mHeadsUpChild;
+ case VISIBLE_TYPE_SINGLELINE:
+ return mSingleLineView;
default:
return mContractedChild;
}
@@ -396,7 +433,9 @@
return VISIBLE_TYPE_EXPANDED;
}
} else {
- if (mContentHeight <= mSmallHeight || noExpandedChild) {
+ if (mIsChildInGroup && !isGroupExpanded()) {
+ return VISIBLE_TYPE_SINGLELINE;
+ } else if (mContentHeight <= mSmallHeight || noExpandedChild) {
return VISIBLE_TYPE_CONTRACTED;
} else {
return VISIBLE_TYPE_EXPANDED;
@@ -405,6 +444,7 @@
}
public void notifyContentUpdated() {
+ updateSingleLineView();
selectLayout(false /* animate */, true /* force */);
if (mContractedChild != null) {
mContractedWrapper.notifyContentUpdated();
@@ -443,6 +483,23 @@
mShowingLegacyBackground = showing;
}
+ public void setIsChildInGroup(boolean isChildInGroup) {
+ mIsChildInGroup = isChildInGroup;
+ updateSingleLineView();
+ }
+
+ public void setStatusBarNotification(StatusBarNotification statusBarNotification) {
+ mStatusBarNotification = statusBarNotification;
+ updateSingleLineView();
+ }
+
+ private void updateSingleLineView() {
+ if (mIsChildInGroup) {
+ mSingleLineView = mHybridViewManager.bindFromNotification(
+ mSingleLineView, mStatusBarNotification.getNotification());
+ }
+ }
+
public void setSubTextVisible(boolean visible) {
if (mExpandedChild != null) {
mExpandedWrapper.setSubTextVisible(visible);
@@ -454,4 +511,8 @@
mHeadsUpWrapper.setSubTextVisible(visible);
}
}
+
+ public void setGroupManager(NotificationGroupManager groupManager) {
+ mGroupManager = groupManager;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
new file mode 100644
index 0000000..8f46e89
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
+
+/**
+ * A hybrid view which may contain information about one ore more notifications.
+ */
+public class HybridNotificationView extends AlphaOptimizedFrameLayout {
+
+ protected final int mSingleLineHeight;
+ protected final int mStartMargin;
+ protected final int mEndMargin;
+ protected TextView mTitleView;
+ protected TextView mTextView;
+
+ public HybridNotificationView(Context context) {
+ this(context, null);
+ }
+
+ public HybridNotificationView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mSingleLineHeight = context.getResources().getDimensionPixelSize(
+ R.dimen.notification_single_line_height);
+ mStartMargin = context.getResources().getDimensionPixelSize(
+ R.dimen.notification_content_margin_start);
+ mEndMargin = context.getResources().getDimensionPixelSize(
+ R.dimen.notification_content_margin_end);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int totalWidth = MeasureSpec.getSize(widthMeasureSpec);
+ int remainingWidth = totalWidth - mStartMargin - mEndMargin;
+ int newHeightSpec = MeasureSpec.makeMeasureSpec(
+ MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.AT_MOST);
+ int newWidthSpec = MeasureSpec.makeMeasureSpec(remainingWidth, MeasureSpec.AT_MOST);
+ mTitleView.measure(newWidthSpec, newHeightSpec);
+ int maxTitleLength = getResources().getDimensionPixelSize(
+ R.dimen.notification_maximum_title_length);
+ int titleWidth = mTitleView.getMeasuredWidth();
+ int heightSpec = MeasureSpec.makeMeasureSpec(mSingleLineHeight, MeasureSpec.AT_MOST);
+ boolean hasText = !TextUtils.isEmpty(mTextView.getText());
+ if (titleWidth > maxTitleLength && hasText) {
+ titleWidth = maxTitleLength;
+ int widthSpec = MeasureSpec.makeMeasureSpec(titleWidth, MeasureSpec.EXACTLY);
+ mTitleView.measure(widthSpec, heightSpec);
+ }
+ if (hasText) {
+ remainingWidth -= titleWidth;
+ int widthSpec = MeasureSpec.makeMeasureSpec(remainingWidth, MeasureSpec.AT_MOST);
+ mTextView.measure(widthSpec, newHeightSpec);
+ }
+ setMeasuredDimension(totalWidth, mSingleLineHeight);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ int childLeft = mStartMargin;
+ int childRight = childLeft + mTitleView.getMeasuredWidth();
+ int childBottom = (mSingleLineHeight + mTitleView.getMeasuredHeight()) / 2;
+ int childTop = childBottom - mTitleView.getMeasuredHeight();
+ int rtlLeft = transformForRtl(childLeft);
+ int rtlRight = transformForRtl(childRight);
+ mTitleView.layout(Math.min(rtlLeft, rtlRight), childTop, Math.max(rtlLeft, rtlRight),
+ childBottom);
+ childLeft = childRight;
+ childRight = childLeft + mTextView.getMeasuredWidth();
+ childTop = mTitleView.getTop() + mTitleView.getBaseline() - mTextView.getBaseline();
+ childBottom = childTop + mTextView.getMeasuredHeight();
+ rtlLeft = transformForRtl(childLeft);
+ rtlRight = transformForRtl(childRight);
+ mTextView.layout(Math.min(rtlLeft, rtlRight), childTop, Math.max(rtlLeft, rtlRight),
+ childBottom);
+ }
+
+ private int transformForRtl(int left) {
+ return isLayoutRtl() ? getWidth() - left : left;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mTitleView = (TextView) findViewById(R.id.notification_title);
+ mTextView = (TextView) findViewById(R.id.notification_text);
+ }
+
+ public void bind(CharSequence title) {
+ bind(title, null);
+ }
+
+ public void bind(CharSequence title, CharSequence text) {
+ mTitleView.setText(title);
+ mTextView.setText(text);
+ requestLayout();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java
new file mode 100644
index 0000000..987f7b8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+
+import java.util.List;
+
+/**
+ * A class managing {@link HybridNotificationView} views
+ */
+public class HybridNotificationViewManager {
+
+ private final Context mContext;
+ private ViewGroup mParent;
+ private String mConcadenationString;
+
+ public HybridNotificationViewManager(Context ctx, ViewGroup parent) {
+ mContext = ctx;
+ mParent = parent;
+ mConcadenationString = mContext.getString(R.string.group_summary_concadenation);
+ }
+
+ private HybridNotificationView inflateHybridView() {
+ LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
+ HybridNotificationView hybrid = (HybridNotificationView) inflater.inflate(
+ R.layout.hybrid_notification, mParent, false);
+ mParent.addView(hybrid);
+ return hybrid;
+ }
+
+ public HybridNotificationView bindFromNotification(HybridNotificationView reusableView,
+ Notification notification) {
+ CharSequence titleText = resolveTitle(notification);
+ if (titleText == null) {
+ if (reusableView != null) {
+ mParent.removeView(reusableView);
+ }
+ return null;
+ }
+ if (reusableView == null) {
+ reusableView = inflateHybridView();
+ }
+ CharSequence contentText = resolveText(notification);
+ reusableView.bind(titleText, contentText);
+ return reusableView;
+ }
+
+ private CharSequence resolveText(Notification notification) {
+ CharSequence contentText = notification.extras.getCharSequence(Notification.EXTRA_BIG_TEXT);
+ if (contentText == null) {
+ contentText = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
+ }
+ return contentText;
+ }
+
+ private CharSequence resolveTitle(Notification notification) {
+ CharSequence titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
+ if (titleText == null) {
+ titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE_BIG);
+ }
+ return titleText;
+ }
+
+ public HybridNotificationView bindFromNotificationGroup(
+ HybridNotificationView reusableView,
+ List<ExpandableNotificationRow> group, int startIndex) {
+ if (reusableView == null) {
+ reusableView = inflateHybridView();
+ }
+ CharSequence summary = null;
+ int childCount = group.size();
+ for (int i = startIndex; i < childCount; i++) {
+ ExpandableNotificationRow child = group.get(i);
+ CharSequence titleText = resolveTitle(
+ child.getStatusBarNotification().getNotification());
+ if (titleText == null) {
+ continue;
+ }
+ if (TextUtils.isEmpty(summary)) {
+ summary = titleText;
+ } else if (reusableView.isLayoutRtl()) {
+ summary = titleText + mConcadenationString + summary;
+ } else {
+ summary = summary + mConcadenationString + titleText;
+ }
+ }
+ reusableView.bind(summary);
+ return reusableView;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index d0b3c4b..bbef1c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -21,7 +21,6 @@
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.StatusBarState;
import java.util.HashMap;
import java.util.HashSet;
@@ -93,21 +92,8 @@
if (group.children.isEmpty()) {
if (group.summary == null) {
mGroupMap.remove(groupKey);
- } else {
- if (group.expanded) {
- // only the summary is left. Change it to unexpanded in a few ms. We do this to
- // avoid raceconditions
- removed.row.post(new Runnable() {
- @Override
- public void run() {
- if (group.children.isEmpty()) {
- setGroupExpanded(sbn, false);
- }
- }
- });
- } else {
- group.summary.row.updateNotificationHeader();
- }
+ } else if (!group.expanded) {
+ group.summary.row.updateNotificationHeader();
}
}
}
@@ -155,9 +141,6 @@
}
public boolean hasGroupChildren(StatusBarNotification sbn) {
- if (areGroupsProhibited()) {
- return false;
- }
if (!sbn.getNotification().isGroupSummary()) {
return false;
}
@@ -168,29 +151,6 @@
return !group.children.isEmpty();
}
- public void setStatusBarState(int newState) {
- if (mBarState == newState) {
- return;
- }
- boolean prohibitedBefore = areGroupsProhibited();
- mBarState = newState;
- boolean nowProhibited = areGroupsProhibited();
- if (nowProhibited != prohibitedBefore) {
- if (nowProhibited) {
- for (NotificationGroup group : mGroupMap.values()) {
- if (group.expanded) {
- setGroupExpanded(group, false);
- }
- }
- }
- mListener.onGroupsProhibitedChanged();
- }
- }
-
- private boolean areGroupsProhibited() {
- return mBarState == StatusBarState.KEYGUARD;
- }
-
/**
* @return whether a given notification is a child in a group which has a summary
*/
@@ -226,6 +186,18 @@
: group.summary.row;
}
+ public void onEntryHeadsUped(NotificationData.Entry headsUp) {
+ // TODO: handle this nicely
+ }
+
+ public void toggleGroupExpansion(StatusBarNotification sbn) {
+ NotificationGroup group = mGroupMap.get(sbn.getGroupKey());
+ if (group == null) {
+ return;
+ }
+ setGroupExpanded(group, !group.expanded);
+ }
+
public static class NotificationGroup {
public final HashSet<NotificationData.Entry> children = new HashSet<>();
public NotificationData.Entry summary;
@@ -242,11 +214,6 @@
void onGroupExpansionChanged(ExpandableNotificationRow changedRow, boolean expanded);
/**
- * Children group policy has changed and children may no be prohibited or allowed.
- */
- void onGroupsProhibitedChanged();
-
- /**
* A group of children just received a summary notification and should therefore become
* children of it.
*
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 deb4402..3e52515 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -714,7 +714,7 @@
R.color.notification_panel_solid_background)));
}
- mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow);
+ mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow, mGroupManager);
mHeadsUpManager.setBar(this);
mHeadsUpManager.addListener(this);
mHeadsUpManager.addListener(mNotificationPanel);
@@ -3859,7 +3859,6 @@
clearNotificationEffects();
}
mState = state;
- mGroupManager.setStatusBarState(state);
mFalsingManager.setStatusBarState(state);
mStatusBarWindowManager.setStatusBarState(state);
updateDozing();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index a515f23..dc9f5e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -33,6 +33,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import java.io.FileDescriptor;
@@ -85,6 +86,7 @@
private final int mStatusBarHeight;
private final int mNotificationsTopPadding;
private final Context mContext;
+ private final NotificationGroupManager mGroupManager;
private PhoneStatusBar mBar;
private int mSnoozeLengthMs;
private ContentObserver mSettingsObserver;
@@ -104,7 +106,8 @@
private boolean mIsObserving;
private boolean mRemoteInputActive;
- public HeadsUpManager(final Context context, View statusBarWindowView) {
+ public HeadsUpManager(final Context context, View statusBarWindowView,
+ NotificationGroupManager groupManager) {
mContext = context;
Resources resources = mContext.getResources();
mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
@@ -132,6 +135,7 @@
Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false,
mSettingsObserver);
mStatusBarWindowView = statusBarWindowView;
+ mGroupManager = groupManager;
mStatusBarHeight = resources.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
mNotificationsTopPadding = context.getResources()
@@ -181,12 +185,12 @@
public void updateNotification(NotificationData.Entry headsUp, boolean alert) {
if (DEBUG) Log.v(TAG, "updateNotification");
- headsUp.row.setChildrenExpanded(false /* expanded */, false /* animated */);
headsUp.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
if (alert) {
HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key);
headsUpEntry.updateEntry();
+ mGroupManager.onEntryHeadsUped(headsUp);
setEntryPinned(headsUpEntry, shouldHeadsUpBecomePinned(headsUp));
}
}
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 da82456..539dace 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -24,7 +24,8 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.notification.HybridNotificationView;
+import com.android.systemui.statusbar.notification.HybridNotificationViewManager;
import java.util.ArrayList;
import java.util.List;
@@ -34,6 +35,10 @@
*/
public class NotificationChildrenContainer extends ViewGroup {
+ private static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2;
+ private static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5;
+ private static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8;
+
private final int mChildPadding;
private final int mDividerHeight;
private final int mMaxNotificationHeight;
@@ -42,6 +47,12 @@
private final int mNotificationHeaderHeight;
private final int mNotificationAppearDistance;
private final float mHeaderTopPaddingSubstraction;
+ private final HybridNotificationViewManager mHybridViewManager;
+ private final float mCollapsedBottompadding;
+ private boolean mChildrenExpanded;
+ private ExpandableNotificationRow mNotificationParent;
+ private HybridNotificationView mGroupOverflowContainer;
+ private ViewState mGroupOverFlowState;
public NotificationChildrenContainer(Context context) {
this(context, null);
@@ -69,6 +80,8 @@
mNotificationHeaderHeight = getResources().getDimensionPixelSize(
R.dimen.notification_header_height);
mHeaderTopPaddingSubstraction = 2 * getResources().getDisplayMetrics().density;
+ mCollapsedBottompadding = 10 * getResources().getDisplayMetrics().density;
+ mHybridViewManager = new HybridNotificationViewManager(getContext(), this);
}
@Override
@@ -78,14 +91,6 @@
for (int i = 0; i < childCount; i++) {
View child = mChildren.get(i);
boolean viewGone = child.getVisibility() == View.GONE;
- if (i != 0) {
- View divider = mDividers.get(i - 1);
- int dividerVisibility = divider.getVisibility();
- int newVisibility = viewGone ? INVISIBLE : VISIBLE;
- if (dividerVisibility != newVisibility) {
- divider.setVisibility(newVisibility);
- }
- }
if (viewGone) {
continue;
}
@@ -96,6 +101,10 @@
firstChild = false;
}
}
+ if (mGroupOverflowContainer != null) {
+ mGroupOverflowContainer.layout(0, 0, getWidth(),
+ mGroupOverflowContainer.getMeasuredHeight());
+ }
}
@Override
@@ -115,9 +124,6 @@
boolean firstChild = true;
for (int i = 0; i < childCount; i++) {
View child = mChildren.get(i);
- if (child.getVisibility() == View.GONE) {
- continue;
- }
child.measure(widthMeasureSpec, newHeightSpec);
height += child.getMeasuredHeight();
if (!firstChild) {
@@ -130,9 +136,9 @@
}
}
int width = MeasureSpec.getSize(widthMeasureSpec);
- height = hasFixedHeight ? ownMaxHeight
- : isHeightLimited ? Math.min(ownMaxHeight, height)
- : height;
+ if (mGroupOverflowContainer != null) {
+ mGroupOverflowContainer.measure(widthMeasureSpec, newHeightSpec);
+ }
setMeasuredDimension(width, height);
}
@@ -151,8 +157,7 @@
addView(divider);
mDividers.add(Math.max(newIndex - 1, 0), divider);
}
- // TODO: adapt background corners
- // TODO: fix overdraw
+ updateGroupOverflow();
}
public void removeNotification(ExpandableNotificationRow row) {
@@ -164,7 +169,26 @@
removeView(divider);
}
row.setSystemChildExpanded(false);
- // TODO: adapt background corners
+ updateGroupOverflow();
+ }
+
+ public void updateGroupOverflow() {
+ int childCount = mChildren.size();
+ int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
+ boolean hasOverflow = childCount > maxAllowedVisibleChildren;
+ int lastVisibleIndex = hasOverflow ? maxAllowedVisibleChildren - 2
+ : maxAllowedVisibleChildren - 1;
+ if (hasOverflow) {
+ mGroupOverflowContainer = mHybridViewManager.bindFromNotificationGroup(
+ mGroupOverflowContainer, mChildren, lastVisibleIndex + 1);
+ if (mGroupOverFlowState == null) {
+ mGroupOverFlowState = new ViewState();
+ }
+ } else if (mGroupOverflowContainer != null) {
+ removeView(mGroupOverflowContainer);
+ mGroupOverflowContainer = null;
+ mGroupOverFlowState = null;
+ }
}
private View inflateDivider() {
@@ -196,25 +220,42 @@
result = true;
}
}
-
- // Let's make the first child expanded!
- boolean first = true;
- for (int i = 0; i < childOrder.size(); i++) {
- ExpandableNotificationRow child = childOrder.get(i);
- child.setSystemChildExpanded(first);
- first = false;
- }
+ updateExpansionStates();
return result;
}
+ private void updateExpansionStates() {
+ // Let's make the first child expanded if the parent is
+ for (int i = 0; i < mChildren.size(); i++) {
+ ExpandableNotificationRow child = mChildren.get(i);
+ child.setSystemChildExpanded(false);
+ }
+ }
+
+ /**
+ *
+ * @return the intrinsic size of this children container, i.e the natural fully expanded state
+ */
public int getIntrinsicHeight() {
- int childCount = mChildren.size();
+ int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
+ return getIntrinsicHeight(maxAllowedVisibleChildren);
+ }
+
+ /**
+ * @return the intrinsic height with a number of children given
+ * in @param maxAllowedVisibleChildren
+ */
+ private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
int intrinsicHeight = 0;
int visibleChildren = 0;
+ int childCount = mChildren.size();
for (int i = 0; i < childCount; i++) {
+ if (visibleChildren >= maxAllowedVisibleChildren) {
+ break;
+ }
ExpandableNotificationRow child = mChildren.get(i);
- if (child.getVisibility() == View.GONE) {
- continue;
+ if (i == 0 && child.hasSameBgColor(mNotificationParent)) {
+ intrinsicHeight -= mHeaderTopPaddingSubstraction;
}
intrinsicHeight += child.getIntrinsicHeight();
visibleChildren++;
@@ -222,6 +263,9 @@
if (visibleChildren > 0) {
intrinsicHeight += (visibleChildren - 1) * mDividerHeight;
}
+ if (!mChildrenExpanded) {
+ intrinsicHeight += mCollapsedBottompadding;
+ }
return intrinsicHeight;
}
@@ -235,15 +279,21 @@
int childCount = mChildren.size();
int yPosition = mNotificationHeaderHeight;
boolean firstChild = true;
+ int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
+ boolean hasOverflow = !mChildrenExpanded && childCount > maxAllowedVisibleChildren
+ && maxAllowedVisibleChildren != NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
+ int lastVisibleIndex = hasOverflow
+ ? maxAllowedVisibleChildren - 2
+ : maxAllowedVisibleChildren - 1;
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
- if (child.getVisibility() == View.GONE) {
- continue;
- }
if (!firstChild) {
// There's a divider
yPosition += mChildPadding;
} else {
+ if (child.hasSameBgColor(mNotificationParent)) {
+ yPosition -= mHeaderTopPaddingSubstraction;
+ }
firstChild = false;
}
StackViewState childState = resultState.getViewStateForView(child);
@@ -255,37 +305,62 @@
childState.dark = parentState.dark;
childState.hideSensitive = parentState.hideSensitive;
childState.belowSpeedBump = parentState.belowSpeedBump;
- childState.scale = parentState.scale;
+ childState.scale = 1.0f;
childState.clipTopAmount = 0;
childState.topOverLap = 0;
+ boolean visible = i <= lastVisibleIndex;
+ childState.alpha = visible ? 1 : 0;
childState.location = parentState.location;
yPosition += intrinsicHeight;
}
+ if (mGroupOverflowContainer != null) {
+ mGroupOverFlowState.initFrom(mGroupOverflowContainer);
+ if (hasOverflow) {
+ StackViewState firstOverflowState =
+ resultState.getViewStateForView(mChildren.get(lastVisibleIndex + 1));
+ mGroupOverFlowState.yTranslation = firstOverflowState.yTranslation;
+ }
+ mGroupOverFlowState.alpha = mChildrenExpanded || !hasOverflow ? 0.0f : 1.0f;
+ }
+ }
+
+ private int getMaxAllowedVisibleChildren() {
+ return getMaxAllowedVisibleChildren(false /* likeCollapsed */);
+ }
+
+ private int getMaxAllowedVisibleChildren(boolean likeCollapsed) {
+ if (!likeCollapsed && (mChildrenExpanded || mNotificationParent.isUserLocked())) {
+ return NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
+ }
+ if (mNotificationParent.isExpanded()) {
+ return NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED;
+ }
+ return NUMBER_OF_CHILDREN_WHEN_COLLAPSED;
}
public void applyState(StackScrollState state) {
int childCount = mChildren.size();
boolean firstChild = true;
- ViewState dividerState = new ViewState();
+ ViewState tmpState = new ViewState();
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
- if (child.getVisibility() == View.GONE) {
- continue;
- }
if (!firstChild) {
// layout the divider
View divider = mDividers.get(i - 1);
- dividerState.initFrom(divider);
- dividerState.yTranslation = (int) (viewState.yTranslation
+ tmpState.initFrom(divider);
+ tmpState.yTranslation = (int) (viewState.yTranslation
- (mChildPadding + mDividerHeight) / 2.0f);
- dividerState.alpha = 1;
- state.applyViewState(divider, dividerState);
+ tmpState.alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
+ state.applyViewState(divider, tmpState);
} else {
firstChild = false;
}
state.applyState(child, viewState);
}
+ if (mGroupOverflowContainer != null) {
+ state.applyViewState(mGroupOverflowContainer, mGroupOverFlowState);
+ }
}
/**
@@ -295,6 +370,10 @@
* @param state the new state we animate to
*/
public void prepareExpansionChanged(StackScrollState state) {
+ if (true) {
+ // TODO: do something that makes sense
+ return;
+ }
int childCount = mChildren.size();
boolean firstChild = true;
StackViewState sourceState = new StackViewState();
@@ -302,9 +381,6 @@
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
- if (child.getVisibility() == View.GONE) {
- continue;
- }
if (!firstChild) {
// layout the divider
View divider = mDividers.get(i - 1);
@@ -321,23 +397,17 @@
sourceState.yTranslation += mNotificationAppearDistance;
state.applyState(child, sourceState);
}
- mCollapseButton.setAlpha(0);
- mCollapseDivider.setAlpha(0);
- mCollapseDivider.setTranslationY(mNotificationAppearDistance / 4);
}
public void startAnimationToState(StackScrollState state, StackStateAnimator stateAnimator,
boolean withDelays, long baseDelay, long duration) {
int childCount = mChildren.size();
boolean firstChild = true;
- ViewState dividerState = new ViewState();
+ ViewState tmpState = new ViewState();
int notGoneIndex = 0;
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
- if (child.getVisibility() == View.GONE) {
- continue;
- }
int difference = Math.min(StackStateAnimator.DELAY_EFFECT_MAX_INDEX_DIFFERENCE_CHILDREN,
notGoneIndex + 1);
long delay = withDelays
@@ -347,17 +417,20 @@
if (!firstChild) {
// layout the divider
View divider = mDividers.get(i - 1);
- dividerState.initFrom(divider);
- dividerState.yTranslation = viewState.yTranslation
+ tmpState.initFrom(divider);
+ tmpState.yTranslation = viewState.yTranslation
- (mChildPadding + mDividerHeight) / 2.0f;
- dividerState.alpha = 1;
- stateAnimator.startViewAnimations(divider, dividerState, delay, duration);
+ tmpState.alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;;
+ stateAnimator.startViewAnimations(divider, tmpState, delay, duration);
} else {
firstChild = false;
}
stateAnimator.startStackAnimations(child, viewState, state, -1, delay);
notGoneIndex++;
}
+ if (mGroupOverflowContainer != null) {
+ stateAnimator.startViewAnimations(mGroupOverflowContainer, mGroupOverFlowState, -1, 0);
+ }
}
public ExpandableNotificationRow getViewAtPosition(float y) {
@@ -375,7 +448,15 @@
return null;
}
- public void setTintColor(int color) {
- ExpandableNotificationRow.applyTint(mCollapseDivider, color);
+ public void setChildrenExpanded(boolean childrenExpanded) {
+ mChildrenExpanded = childrenExpanded;
+ }
+
+ public int getMaxContentHeight() {
+ return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
+ }
+
+ public int getMinHeight() {
+ return getIntrinsicHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */));
}
}
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 1b66073..573e45b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1726,7 +1726,7 @@
ExpandableNotificationRow groupSummary =
mGroupManager.getGroupSummary(row.getStatusBarNotification());
if (groupSummary != null && groupSummary != row) {
- return !groupSummary.areChildrenExpanded();
+ return row.getVisibility() == View.INVISIBLE;
}
}
return false;
@@ -2800,10 +2800,6 @@
}
@Override
- public void onGroupsProhibitedChanged() {
- }
-
- @Override
public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
for (NotificationData.Entry entry : group.children) {
ExpandableNotificationRow row = entry.row;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index cf696a1..65ca95b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -361,7 +361,7 @@
// handle the notgoneIndex for the children as well
List<ExpandableNotificationRow> children =
row.getNotificationChildren();
- if (row.areChildrenExpanded() && children != null) {
+ if (row.isSummaryWithChildren() && children != null) {
for (ExpandableNotificationRow childRow : children) {
if (childRow.getVisibility() != View.GONE) {
StackViewState childState
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 3768ca4..e155d70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -65,7 +65,7 @@
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
List<ExpandableNotificationRow> children =
row.getNotificationChildren();
- if (row.areChildrenExpanded() && children != null) {
+ if (row.isSummaryWithChildren() && children != null) {
for (ExpandableNotificationRow childRow : children) {
resetViewState(childRow);
}