summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java142
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java3
5 files changed, 116 insertions, 98 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 9fd0e4c54d40..bba411c3f99a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1765,7 +1765,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
public static class NotificationViewState extends ExpandableViewState {
private final StackScrollState mOverallState;
- public float iconTransformationAmount;
private NotificationViewState(StackScrollState stackScrollState) {
@@ -1781,7 +1780,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
row.setClipToActualHeight(true);
}
row.applyChildrenState(mOverallState);
- row.setIconTransformationAmount(iconTransformationAmount);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index ff644ea10171..8a6ce56913b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState;
+
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
@@ -29,9 +31,9 @@ import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.stack.AmbientState;
import com.android.systemui.statusbar.stack.ExpandableViewState;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.stack.StackScrollState;
-import com.android.systemui.statusbar.stack.ViewState;
import java.util.ArrayList;
import java.util.WeakHashMap;
@@ -52,6 +54,8 @@ public class NotificationShelf extends ActivatableNotificationView {
private int mIconAppearTopPadding;
private int mStatusBarHeight;
private int mStatusBarPaddingStart;
+ private AmbientState mAmbientState;
+ private NotificationStackScrollLayout mHostLayout;
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -70,10 +74,14 @@ public class NotificationShelf extends ActivatableNotificationView {
mViewInvertHelper = new ViewInvertHelper(mNotificationIconContainer,
NotificationPanelView.DOZE_ANIMATION_DURATION);
mShelfState = new ShelfState();
- mShelfState.iconStates = mNotificationIconContainer.getIconStates();
initDimens();
}
+ public void bind(AmbientState ambientState, NotificationStackScrollLayout hostLayout) {
+ mAmbientState = ambientState;
+ mHostLayout = hostLayout;
+ }
+
private void initDimens() {
mIconAppearTopPadding = getResources().getDimensionPixelSize(
R.dimen.notification_icon_appear_padding);
@@ -140,60 +148,63 @@ public class NotificationShelf extends ActivatableNotificationView {
mShelfState.shadowAlpha = 1.0f;
mShelfState.isBottomClipped = false;
mShelfState.hideSensitive = false;
-
- mShelfState.resetIcons();
- float numIconsInShelf = 0.0f;
- float viewStart;
- float maxShelfStart = maxShelfEnd - mShelfState.height;
- // find the first view that doesn't overlap with the shelf
- for (int i = shelfIndex; i >= 0; i--) {
- lastView = algorithmState.visibleChildren.get(i);
- lastViewState = resultState.getViewStateForView(lastView);
- ExpandableNotificationRow row = null;
- if (lastView instanceof ExpandableNotificationRow) {
- row = (ExpandableNotificationRow) lastView;
- }
- viewStart = lastViewState.yTranslation;
- viewEnd = viewStart + lastView.getIntrinsicHeight();
- if (viewEnd > maxShelfStart) {
- if (viewStart < maxShelfStart) {
- float transitionAmount = 1.0f - ((maxShelfStart - viewStart) /
- lastView.getIntrinsicHeight());
- numIconsInShelf += transitionAmount;
- } else {
- numIconsInShelf += 1.0f;
- lastViewState.hidden = true;
- }
- }
- if (row != null){
- // Not in the shelf yet, Icon needs to be placed on top of the notification icon
- updateIconAppearance(row.getEntry(),
- (ExpandableNotificationRow.NotificationViewState) lastViewState,
- mShelfState);
- }
- }
- mShelfState.iconStates = mNotificationIconContainer.calculateIconStates(
- numIconsInShelf);
- mShelfState.hidden = numIconsInShelf == 0.0f;
- mShelfState.hideBackground = numIconsInShelf < 1.0f;
} else {
- mShelfState.hideBackground = true;
mShelfState.hidden = true;
mShelfState.location = ExpandableViewState.LOCATION_GONE;
}
}
- private float getFullyClosedTranslation() {
- return - (getIntrinsicHeight() - mStatusBarHeight) / 2;
+ /**
+ * Update the shelf appearance based on the other notifications around it. This transforms
+ * the icons from the notification area into the shelf.
+ */
+ public void updateAppearance() {
+ WeakHashMap<View, IconState> iconStates =
+ mNotificationIconContainer.resetViewStates();
+ float numIconsInShelf = 0.0f;
+ float maxShelfStart = getTranslationY();
+ int shelfIndex = mAmbientState.getShelfIndex() - 1;
+ // find the first view that doesn't overlap with the shelf
+ for (int i = shelfIndex; i >= 0; i--) {
+ ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
+ if (!(child instanceof ExpandableNotificationRow)
+ || child.getVisibility() == GONE) {
+ continue;
+ }
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ StatusBarIconView icon = row.getEntry().expandedIcon;
+ IconState iconState = iconStates.get(icon);
+ updateIconAppearance(maxShelfStart, row, iconState, icon);
+ numIconsInShelf += iconState.iconAppearAmount;
+ }
+ mNotificationIconContainer.calculateIconTranslations();
+ mNotificationIconContainer.applyIconStates();
+ setVisibility(numIconsInShelf == 0.0f ? INVISIBLE : VISIBLE);
+ setHideBackground(numIconsInShelf < 1.0f);
}
- private void updateIconAppearance(NotificationData.Entry entry,
- ExpandableNotificationRow.NotificationViewState rowState,
- ShelfState shelfState) {
- StatusBarIconView icon = entry.expandedIcon;
- ViewState iconState = shelfState.iconStates.get(icon);
- View rowIcon = entry.row.getNotificationIcon();
- float notificationIconPosition = rowState.yTranslation;
+ private void updateIconAppearance(float maxShelfStart, ExpandableNotificationRow row,
+ IconState iconState, StatusBarIconView icon) {
+
+ // Let calculate how much the view is in the shelf
+ float viewStart = row.getTranslationY();
+ float viewEnd = viewStart + row.getIntrinsicHeight();
+ if (viewEnd > maxShelfStart) {
+ if (viewStart < maxShelfStart) {
+ iconState.iconAppearAmount = 1.0f - ((maxShelfStart - viewStart) /
+ row.getIntrinsicHeight());
+ } else {
+ iconState.iconAppearAmount = 1.0f;
+ }
+ } else {
+ iconState.iconAppearAmount = 0.0f;
+ }
+
+ // Lets now calculate how much of the transformation has already happened. This is different
+ // from the above, since we only start transforming when the view is already quite a bit
+ // pushed in.
+ View rowIcon = row.getNotificationIcon();
+ float notificationIconPosition = viewStart;
float notificationIconSize = 0.0f;
int iconTopPadding;
if (rowIcon != null) {
@@ -203,31 +214,39 @@ public class NotificationShelf extends ActivatableNotificationView {
iconTopPadding = mIconAppearTopPadding;
}
notificationIconPosition += iconTopPadding;
- float shelfIconPosition = mShelfState.yTranslation + icon.getTop();
+ float shelfIconPosition = getTranslationY() + icon.getTop();
shelfIconPosition += ((1.0f - icon.getIconScale()) * icon.getHeight()) / 2.0f;
float transitionDistance = getIntrinsicHeight() * 1.5f;
- float transformationStartPosition = mShelfState.yTranslation - transitionDistance;
+ float transformationStartPosition = getTranslationY() - transitionDistance;
float transitionAmount = 0.0f;
- if (rowState.yTranslation < transformationStartPosition) {
+ if (viewStart < transformationStartPosition) {
// We simply place it on the icon of the notification
iconState.yTranslation = notificationIconPosition - shelfIconPosition;
} else {
- transitionAmount = (rowState.yTranslation - transformationStartPosition)
+ transitionAmount = (viewStart - transformationStartPosition)
/ transitionDistance;
float startPosition = transformationStartPosition + iconTopPadding;
iconState.yTranslation = NotificationUtils.interpolate(
startPosition - shelfIconPosition, 0, transitionAmount);
}
float shelfIconSize = icon.getHeight() * icon.getIconScale();
- Float newSize = NotificationUtils.interpolate(notificationIconSize, shelfIconSize,
+ if (!row.isShowingIcon()) {
+ // The view currently doesn't have an icon, lets transform it in!
+ iconState.alpha = transitionAmount;
+ notificationIconSize = shelfIconSize / 2.0f;
+ }
+ // The notification size is different from the size in the shelf / statusbar
+ float newSize = NotificationUtils.interpolate(notificationIconSize, shelfIconSize,
transitionAmount);
iconState.scaleX = newSize / icon.getHeight();
iconState.scaleY = iconState.scaleX;
iconState.hidden = transitionAmount == 0.0f;
- rowState.iconTransformationAmount = transitionAmount;
- if (!entry.row.isShowingIcon()) {
- iconState.alpha = transitionAmount;
- }
+ row.setIconTransformationAmount(transitionAmount);
+ icon.setVisibility(transitionAmount == 0.0f ? INVISIBLE : VISIBLE);
+ }
+
+ private float getFullyClosedTranslation() {
+ return - (getIntrinsicHeight() - mStatusBarHeight) / 2;
}
private int getIconTopPadding(View icon) {
@@ -273,20 +292,13 @@ public class NotificationShelf extends ActivatableNotificationView {
}
private class ShelfState extends ExpandableViewState {
- private WeakHashMap<View, ViewState> iconStates = new WeakHashMap<>();
- private boolean hideBackground;
private float iconContainerTranslation;
@Override
public void applyToView(View view) {
super.applyToView(view);
- mNotificationIconContainer.applyIconStates(iconStates);
- setHideBackground(hideBackground);
+ updateAppearance();
setIconContainerTranslation(iconContainerTranslation);
}
-
- public void resetIcons() {
- mNotificationIconContainer.resetViewStates(iconStates);
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index bf7886d93a3e..11563d5945cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -34,7 +34,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
private boolean mShowAllIcons = true;
private int mIconTint;
- private WeakHashMap<View, ViewState> mIconStates = new WeakHashMap<>();
+ private WeakHashMap<View, IconState> mIconStates = new WeakHashMap<>();
public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -54,16 +54,16 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
child.layout(0, top, width, top + height);
}
if (mShowAllIcons) {
- resetViewStates(mIconStates);
- calculateIconStates(getChildCount());
- applyIconStates(mIconStates);
+ resetViewStates();
+ calculateIconTranslations();
+ applyIconStates();
}
}
- public void applyIconStates(WeakHashMap<View, ViewState> iconStates) {
+ public void applyIconStates() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
- ViewState childState = iconStates.get(child);
+ ViewState childState = mIconStates.get(child);
if (childState != null) {
childState.applyToView(child);
}
@@ -73,7 +73,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
- mIconStates.put(child, new ViewState());
+ mIconStates.put(child, new IconState());
}
@Override
@@ -86,42 +86,33 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
mIconTint = iconTint;
}
- public void resetViewStates(WeakHashMap<View, ViewState> viewStates) {
+ public WeakHashMap<View, IconState> resetViewStates() {
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
ViewState iconState = mIconStates.get(view);
iconState.initFrom(view);
}
+ return mIconStates;
}
/**
- * Gets a new state based on the number of visible icons starting from the right.
+ * Calulate the horizontal translations for each notification based on how much the icons
+ * are inserted into the notification container.
* If this is not a whole number, the fraction means by how much the icon is appearing.
*/
- public WeakHashMap<View, ViewState> calculateIconStates(float numberOfVisibleIcons) {
+ public WeakHashMap<View, IconState> calculateIconTranslations() {
int childCount = getChildCount();
float visibleIconStart = childCount - numberOfVisibleIcons;
- int firstIconIndex = (int) visibleIconStart;
float translationX = 0.0f;
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
- ViewState iconState = mIconStates.get(view);
- if (i >= firstIconIndex) {
- iconState.xTranslation = translationX;
- float appearAmount = 1.0f;
- if (i == firstIconIndex) {
- appearAmount = 1.0f - (visibleIconStart - firstIconIndex);
- }
- translationX += appearAmount * view.getWidth();
- }
+ IconState iconState = mIconStates.get(view);
+ iconState.xTranslation = translationX;
+ translationX += iconState.iconAppearAmount * view.getWidth();
}
return mIconStates;
}
- public WeakHashMap<View, ViewState> getIconStates() {
- return mIconStates;
- }
-
/**
* Sets whether the layout should always show all icons.
* If this is true, the icon positions will be updated on layout.
@@ -131,4 +122,13 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
public void setShowAllIcons(boolean showAllIcons) {
mShowAllIcons = showAllIcons;
}
+
+ public static class IconState extends ViewState {
+ public float iconAppearAmount = 1.0f;
+
+ @Override
+ public void applyToView(View view) {
+ super.applyToView(view);
+ }
+ }
}
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 d04672338027..d35e4a5d6b47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -264,14 +264,11 @@ public class NotificationStackScrollLayout extends ViewGroup
private final ArrayList<Pair<ExpandableNotificationRow, Boolean>> mTmpList = new ArrayList<>();
private FalsingManager mFalsingManager;
private boolean mAnimationRunning;
- private ViewTreeObserver.OnPreDrawListener mBackgroundUpdater
+ private ViewTreeObserver.OnPreDrawListener mRunningAnimationUpdater
= new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- // if it needs animation
- if (!mNeedsAnimation && !mChildrenUpdateRequested) {
- updateBackground();
- }
+ onPreDrawDuringAnimation();
return true;
}
};
@@ -594,6 +591,13 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ private void onPreDrawDuringAnimation() {
+ if (!mNeedsAnimation && !mChildrenUpdateRequested) {
+ updateBackground();
+ }
+ mShelf.updateAppearance();
+ }
+
private void updateScrollStateForAddedChildren() {
if (mChildrenToAddAnimated.isEmpty()) {
return;
@@ -3873,9 +3877,9 @@ public class NotificationStackScrollLayout extends ViewGroup
public void setAnimationRunning(boolean animationRunning) {
if (animationRunning != mAnimationRunning) {
if (animationRunning) {
- getViewTreeObserver().addOnPreDrawListener(mBackgroundUpdater);
+ getViewTreeObserver().addOnPreDrawListener(mRunningAnimationUpdater);
} else {
- getViewTreeObserver().removeOnPreDrawListener(mBackgroundUpdater);
+ getViewTreeObserver().removeOnPreDrawListener(mRunningAnimationUpdater);
}
mAnimationRunning = animationRunning;
updateContinuousShadowDrawing();
@@ -3950,6 +3954,7 @@ public class NotificationStackScrollLayout extends ViewGroup
}
addView(mShelf, index);
mAmbientState.setShelf(shelf);
+ shelf.bind(mAmbientState, this);
}
public NotificationShelf getNotificationShelf() {
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 1b3afe76f1b9..8b40188b2841 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -506,6 +506,9 @@ public class StackScrollAlgorithm {
}
childViewState.height = (int) newHeight;
}
+ if (childViewState.yTranslation >= shelfStart) {
+ childViewState.hidden = true;
+ }
}
protected int getMaxAllowedChildHeight(View child) {