Merge "Fixed the icon clipping of the notification shelf" into oc-mr1-dev
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index b27dedd..2148c80 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -59,6 +59,7 @@
     <item type="id" name="transformation_start_y_tag"/>
     <item type="id" name="transformation_start_scale_x_tag"/>
     <item type="id" name="transformation_start_scale_y_tag"/>
+    <item type="id" name="continuous_clipping_tag"/>
 
     <!-- Whether the icon is from a notification for which targetSdk < L -->
     <item type="id" name="icon_is_pre_L"/>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 5eefe9a..184b95d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -22,10 +22,12 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Rect;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.systemui.Interpolators;
@@ -53,6 +55,7 @@
             SystemProperties.getBoolean("debug.icon_opening_animations", true);
     private static final boolean ICON_ANMATIONS_WHILE_SCROLLING
             = SystemProperties.getBoolean("debug.icon_scroll_animations", true);
+    private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
     private ViewInvertHelper mViewInvertHelper;
     private boolean mDark;
     private NotificationIconContainer mShelfIcons;
@@ -305,6 +308,16 @@
         mShelfIcons.setSpeedBumpIndex(mAmbientState.getSpeedBumpIndex());
         mShelfIcons.calculateIconTranslations();
         mShelfIcons.applyIconStates();
+        for (int i = 0; i < mHostLayout.getChildCount(); i++) {
+            View child = mHostLayout.getChildAt(i);
+            if (!(child instanceof ExpandableNotificationRow)
+                    || child.getVisibility() == GONE) {
+                continue;
+            }
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            updateIconClipAmount(row);
+            updateContinuousClipping(row);
+        }
         boolean hideBackground = numViewsInShelf < 1.0f;
         setHideBackground(hideBackground || backgroundForceHidden);
         if (mNotGoneIndex == -1) {
@@ -312,6 +325,43 @@
         }
     }
 
+    private void updateIconClipAmount(ExpandableNotificationRow row) {
+        float maxTop = row.getTranslationY();
+        StatusBarIconView icon = row.getEntry().expandedIcon;
+        float shelfIconPosition = getTranslationY() + icon.getTop() + icon.getTranslationY();
+        if (shelfIconPosition < maxTop) {
+            int top = (int) (maxTop - shelfIconPosition);
+            Rect clipRect = new Rect(0, top, icon.getWidth(), Math.max(top, icon.getHeight()));
+            icon.setClipBounds(clipRect);
+        } else {
+            icon.setClipBounds(null);
+        }
+    }
+
+    private void updateContinuousClipping(final ExpandableNotificationRow row) {
+        StatusBarIconView icon = row.getEntry().expandedIcon;
+        boolean needsContinuousClipping = ViewState.isAnimatingY(icon);
+        boolean isContinuousClipping = icon.getTag(TAG_CONTINUOUS_CLIPPING) != null;
+        if (needsContinuousClipping && !isContinuousClipping) {
+            ViewTreeObserver.OnPreDrawListener predrawListener =
+                    new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            boolean animatingY = ViewState.isAnimatingY(icon);
+                            if (!animatingY || !icon.isAttachedToWindow()) {
+                                icon.getViewTreeObserver().removeOnPreDrawListener(this);
+                                icon.setTag(TAG_CONTINUOUS_CLIPPING, null);
+                                return true;
+                            }
+                            updateIconClipAmount(row);
+                            return true;
+                        }
+                    };
+            icon.getViewTreeObserver().addOnPreDrawListener(predrawListener);
+            icon.setTag(TAG_CONTINUOUS_CLIPPING, predrawListener);
+        }
+    }
+
     private void updateNotificationClipHeight(ExpandableNotificationRow row,
             float notificationClipEnd) {
         float viewEnd = row.getTranslationY() + row.getActualHeight();