Limit notifications on lockscreen to a maximum 4.
All the other notifications are going to be collapsed in a "n more"
card.
Bug: 13635952
Change-Id: I18471c7b18d05d27e92c49ee8214605f1a151927
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
new file mode 100644
index 0000000..79b03ce
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -0,0 +1,51 @@
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <com.android.systemui.statusbar.LatestItemView
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:layout_marginTop="@dimen/notification_divider_height"
+ android:focusable="true"
+ android:clickable="true"
+ android:background="@*android:drawable/notification_quantum_bg_dim"
+ >
+ <TextView
+ android:id="@+id/more_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:gravity="center_horizontal"
+ android:textColor="@color/keyguard_overflow_content_color"
+ android:textAllCaps="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+ <com.android.systemui.statusbar.NotificationOverflowIconsView
+ android:id="@+id/overflow_icons_view"
+ android:layout_gravity="end|center_vertical"
+ android:gravity="end"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:layout_width="120dp"
+ android:layout_height="wrap_content"
+ />
+ </com.android.systemui.statusbar.LatestItemView>
+</FrameLayout>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 5cf0453..1a5ffa9 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -45,4 +45,7 @@
<!-- Tint color for active Quick Settings icons. -->
<color name="ic_qs_on">#ffffffff</color>
+
+ <!-- Tint color for the content on the notification overflow card. -->
+ <color name="keyguard_overflow_content_color">#ff666666</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 672c1d0..e305d94 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -114,5 +114,9 @@
<integer name="recents_filter_animate_new_views_min_duration">125</integer>
<!-- The min animation duration for animating views that are newly visible. -->
<integer name="recents_animate_task_bar_enter_duration">200</integer>
+
+ <!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
+ card. -->
+ <integer name="keyguard_max_notification_count">4</integer>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ad10545..d994a5b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -534,4 +534,9 @@
</plurals>
<!-- Zen mode: Summary notification content text. [CHAR LIMIT=NONE] -->
<string name="zen_mode_notification_text">Touch to show</string>
+
+ <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=12] -->
+ <plurals name="keyguard_more_overflow_text">
+ <item quantity="other">%d more</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index e22e037..d2e032f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -168,6 +168,8 @@
protected int mZenMode;
protected boolean mOnKeyguard;
+ protected View mKeyguardIconOverflowContainer;
+ protected NotificationOverflowIconsView mOverflowIconsView;
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -1051,11 +1053,19 @@
}
/**
+ * @return The number of notifications we show on Keyguard.
+ */
+ protected abstract int getMaxKeyguardNotifications();
+
+ /**
* Updates expanded, dimmed and locked states of notification rows.
*/
protected void updateRowStates() {
+ int maxKeyguardNotifications = getMaxKeyguardNotifications();
+ mOverflowIconsView.removeAllViews();
int n = mNotificationData.size();
- for (int i = 0; i < n; i++) {
+ int visibleNotifications = 0;
+ for (int i = n-1; i >= 0; i--) {
NotificationData.Entry entry = mNotificationData.get(i);
if (mOnKeyguard) {
entry.row.setExpanded(false);
@@ -1067,7 +1077,28 @@
}
entry.row.setDimmed(mOnKeyguard);
entry.row.setLocked(mOnKeyguard);
+ boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
+ if (mOnKeyguard && (visibleNotifications >= maxKeyguardNotifications
+ || !showOnKeyguard)) {
+ entry.row.setVisibility(View.GONE);
+ if (showOnKeyguard) {
+ mOverflowIconsView.addNotification(entry);
+ }
+ } else {
+ entry.row.setVisibility(View.VISIBLE);
+ visibleNotifications++;
+ }
}
+
+ if (mOnKeyguard && mOverflowIconsView.getChildCount() > 0) {
+ mKeyguardIconOverflowContainer.setVisibility(View.VISIBLE);
+ } else {
+ mKeyguardIconOverflowContainer.setVisibility(View.GONE);
+ }
+ }
+
+ private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
+ return sbn.getNotification().priority >= Notification.PRIORITY_LOW;
}
protected void setZenMode(int mode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
new file mode 100644
index 0000000..ce31894
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.IconMerger;
+
+/**
+ * A view to display all the overflowing icons on Keyguard.
+ */
+public class NotificationOverflowIconsView extends IconMerger {
+
+ private TextView mMoreText;
+ private int mTintColor;
+
+ public NotificationOverflowIconsView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mTintColor = getResources().getColor(R.color.keyguard_overflow_content_color);
+ }
+
+ public void setMoreText(TextView moreText) {
+ mMoreText = moreText;
+ }
+
+ public void addNotification(NotificationData.Entry notification) {
+ StatusBarIconView v = new StatusBarIconView(getContext(), "",
+ notification.notification.getNotification());
+ v.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ v.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
+ addView(v);
+ v.set(notification.icon.getStatusBarIcon());
+ updateMoreText();
+ }
+
+ private void updateMoreText() {
+ mMoreText.setText(getResources().getQuantityString(
+ R.plurals.keyguard_more_overflow_text, getChildCount(), getChildCount()));
+ }
+}
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 2d1f3aa..a8b86a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -68,6 +68,7 @@
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -95,8 +96,10 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.InterceptedNotifications;
+import com.android.systemui.statusbar.LatestItemView;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.NotificationOverflowIconsView;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -218,6 +221,7 @@
// top bar
View mNotificationPanelHeader;
View mKeyguardStatusView;
+ int mKeyguardMaxNotificationCount;
View mDateTimeView;
View mClearButton;
ImageView mSettingsButton, mNotificationButton;
@@ -515,6 +519,15 @@
mStackScroller.setLongPressListener(getNotificationLongClicker());
mStackScroller.setChildLocationsChangedListener(mOnChildLocationsChangedListener);
+ mKeyguardIconOverflowContainer = LayoutInflater.from(mContext).inflate(
+ R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
+ ((LatestItemView) mKeyguardIconOverflowContainer.findViewById(R.id.container)).setLocked(true);
+ mOverflowIconsView = (NotificationOverflowIconsView) mKeyguardIconOverflowContainer.findViewById(
+ R.id.overflow_icons_view);
+ mOverflowIconsView.setMoreText(
+ (TextView) mKeyguardIconOverflowContainer.findViewById(R.id.more_text));
+ mStackScroller.addView(mKeyguardIconOverflowContainer);
+
mExpandedContents = mStackScroller;
mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
@@ -1117,7 +1130,7 @@
ArrayList<View> toRemove = new ArrayList<View>();
for (int i=0; i< mStackScroller.getChildCount(); i++) {
View child = mStackScroller.getChildAt(i);
- if (!toShow.contains(child)) {
+ if (!toShow.contains(child) && child != mKeyguardIconOverflowContainer) {
toRemove.add(child);
}
}
@@ -2630,6 +2643,8 @@
mHeadsUpNotificationDecay = res.getInteger(R.integer.heads_up_notification_decay);
mRowHeight = res.getDimensionPixelSize(R.dimen.notification_row_min_height);
+ mKeyguardMaxNotificationCount = res.getInteger(R.integer.keyguard_max_notification_count);
+
if (false) Log.v(TAG, "updateResources");
}
@@ -2853,6 +2868,11 @@
mNotificationPanel.setExpandedFraction(1);
}
+ @Override
+ protected int getMaxKeyguardNotifications() {
+ return mKeyguardMaxNotificationCount;
+ }
+
/**
* @return a ViewGroup that spans the entire panel which contains the quick settings
*/
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 e2d6c5b..8cb9cf2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -656,9 +656,11 @@
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
- height += child.getHeight();
- if (i < getChildCount()-1) {
- height += mPaddingBetweenElements;
+ if (child.getVisibility() != View.GONE) {
+ height += child.getHeight();
+ if (i < getChildCount()-1) {
+ height += mPaddingBetweenElements;
+ }
}
}
mContentHeight = height;
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 4745f3b..47c7c79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -22,6 +22,8 @@
import android.view.ViewGroup;
import com.android.systemui.R;
+import java.util.ArrayList;
+
/**
* The Algorithm of the {@link com.android.systemui.statusbar.stack
* .NotificationStackScrollLayout} which can be queried for {@link com.android.systemui.statusbar
@@ -92,6 +94,7 @@
algorithmState.lastTopStackIndex = 0;
algorithmState.scrollY = resultState.getScrollY();
algorithmState.itemsInBottomStack = 0.0f;
+ updateVisibleChildren(resultState, algorithmState);
// Phase 1:
findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState);
@@ -107,6 +110,23 @@
}
/**
+ * Update the visible children on the state.
+ */
+ private void updateVisibleChildren(StackScrollState resultState,
+ StackScrollAlgorithmState state) {
+ ViewGroup hostView = resultState.getHostView();
+ int childCount = hostView.getChildCount();
+ state.visibleChildren.clear();
+ state.visibleChildren.ensureCapacity(childCount);
+ for (int i = 0; i < childCount; i++) {
+ View v = hostView.getChildAt(i);
+ if (v.getVisibility() != View.GONE) {
+ state.visibleChildren.add(v);
+ }
+ }
+ }
+
+ /**
* Determine the positions for the views. This is the main part of the algorithm.
*
* @param resultState The result state to update if a change to the properties of a child occurs
@@ -126,11 +146,10 @@
// How far in is the element currently transitioning into the bottom stack.
float yPositionInScrollView = 0.0f;
- ViewGroup hostView = resultState.getHostView();
- int childCount = hostView.getChildCount();
+ int childCount = algorithmState.visibleChildren.size();
int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack;
for (int i = 0; i < childCount; i++) {
- View child = hostView.getChildAt(i);
+ View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
childViewState.yTranslation = currentYPosition;
childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
@@ -282,12 +301,11 @@
// The y Position if the element would be in a regular scrollView
float yPositionInScrollView = 0.0f;
- ViewGroup hostView = resultState.getHostView();
- int childCount = hostView.getChildCount();
+ int childCount = algorithmState.visibleChildren.size();
// find the number of elements in the top stack.
for (int i = 0; i < childCount; i++) {
- View child = hostView.getChildAt(i);
+ View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
int childHeight = child.getHeight();
float yPositionInScrollViewAfterElement = yPositionInScrollView
@@ -353,9 +371,10 @@
private void updateZValuesForState(StackScrollState resultState,
StackScrollAlgorithmState algorithmState) {
ViewGroup hostView = resultState.getHostView();
- int childCount = hostView.getChildCount();
+ int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
- View child = hostView.getChildAt(i);
+ View child = algorithmState.visibleChildren.get(i);
+ if (child.getVisibility() == View.GONE) continue;
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
if (i < algorithmState.itemsInTopStack) {
float stackIndex = algorithmState.itemsInTopStack - i;
@@ -415,6 +434,11 @@
* how far in is the element currently transitioning into the bottom stack
*/
public float partialInBottom;
+
+ /**
+ * The children from the host view which are not gone.
+ */
+ public final ArrayList<View> visibleChildren = new ArrayList<View>();
}
}
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 67a1735..06a08f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -63,7 +63,8 @@
}
// initialize with the default values of the view
viewState.height = child.getHeight();
- viewState.alpha = 1.0f;
+ viewState.alpha = 1;
+ viewState.gone = child.getVisibility() == View.GONE;
}
}
@@ -116,7 +117,7 @@
// apply visibility
int oldVisibility = child.getVisibility();
int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
- if (newVisibility != oldVisibility) {
+ if (newVisibility != oldVisibility && !state.gone) {
child.setVisibility(newVisibility);
}
@@ -164,6 +165,7 @@
float yTranslation;
float zTranslation;
int height;
+ boolean gone;
/**
* The location this view is currently rendered at.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index a57a7b5..d615542 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -138,6 +138,11 @@
}
@Override
+ protected int getMaxKeyguardNotifications() {
+ return 0;
+ }
+
+ @Override
public void animateExpandSettingsPanel() {
}