Add separate background colors to each popup container child.

- Colors interpolate between the primary and secondary popup colors
- Removed condensed height and icon scale

Bug: 175329686
Test: visual, manual checking apps with different shortcut options
Change-Id: I064c329dc8ad3ae6f408056c74372cca3ce20b68
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c0ea2fe..10bcb8f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -179,7 +179,6 @@
     <dimen name="deep_shortcuts_elevation">0dp</dimen>
     <dimen name="bg_popup_item_width">234dp</dimen>
     <dimen name="bg_popup_item_height">56dp</dimen>
-    <dimen name="bg_popup_item_condensed_height">48dp</dimen>
     <dimen name="pre_drag_view_scale">6dp</dimen>
     <!-- an icon with shortcuts must be dragged this far before the container is removed. -->
     <dimen name="deep_shortcuts_start_drag_threshold">16dp</dimen>
diff --git a/src/com/android/launcher3/notification/NotificationItemView.java b/src/com/android/launcher3/notification/NotificationItemView.java
index d44d158..e954480 100644
--- a/src/com/android/launcher3/notification/NotificationItemView.java
+++ b/src/com/android/launcher3/notification/NotificationItemView.java
@@ -92,6 +92,10 @@
         });
     }
 
+    public void updateBackgroundColor(int color) {
+        mMainView.updateBackgroundColor(color);
+    }
+
     public void addGutter() {
         if (mGutter == null) {
             mGutter = mPopupContainer.inflateAndAdd(R.layout.notification_gutter, mRootView);
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index 9b06523..c995666 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -97,15 +97,24 @@
         super.onFinishInflate();
 
         mTextAndBackground = findViewById(R.id.text_and_background);
-        ColorDrawable colorBackground = (ColorDrawable) mTextAndBackground.getBackground();
-        mBackgroundColor = colorBackground.getColor();
-        RippleDrawable rippleBackground = new RippleDrawable(ColorStateList.valueOf(
-                Themes.getAttrColor(getContext(), android.R.attr.colorControlHighlight)),
-                colorBackground, null);
-        mTextAndBackground.setBackground(rippleBackground);
         mTitleView = mTextAndBackground.findViewById(R.id.title);
         mTextView = mTextAndBackground.findViewById(R.id.text);
         mIconView = findViewById(R.id.popup_item_icon);
+
+        ColorDrawable colorBackground = (ColorDrawable) mTextAndBackground.getBackground();
+        updateBackgroundColor(colorBackground.getColor());
+    }
+
+    public void updateBackgroundColor(int color) {
+        mBackgroundColor = color;
+        RippleDrawable rippleBackground = new RippleDrawable(ColorStateList.valueOf(
+                Themes.getAttrColor(getContext(), android.R.attr.colorControlHighlight)),
+                new ColorDrawable(color), null);
+        mTextAndBackground.setBackground(rippleBackground);
+        if (mNotificationInfo != null) {
+            mIconView.setBackground(mNotificationInfo.getIconForBackground(getContext(),
+                    mBackgroundColor));
+        }
     }
 
     public void setSwipeDetector(SingleAxisSwipeDetector swipeDetector) {
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 6aa9812..a53fe1f 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -17,10 +17,12 @@
 package com.android.launcher3.popup;
 
 import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
+import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
+import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
@@ -28,6 +30,8 @@
 import android.content.res.Resources;
 import android.graphics.Outline;
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
 import android.util.AttributeSet;
 import android.util.Pair;
@@ -63,6 +67,9 @@
  */
 public abstract class ArrowPopup<T extends BaseDraggingActivity> extends AbstractFloatingView {
 
+    // +1 for system shortcut view
+    private static final int MAX_NUM_CHILDREN = MAX_SHORTCUTS + 1;
+
     private final Rect mTempRect = new Rect();
 
     protected final LayoutInflater mInflater;
@@ -93,6 +100,9 @@
 
     private Runnable mOnCloseCallback = () -> { };
 
+    private int mArrowColor;
+    private final int[] mColors;
+
     public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         mInflater = LayoutInflater.from(context);
@@ -121,15 +131,22 @@
         mArrowPointRadius = resources.getDimensionPixelSize(R.dimen.popup_arrow_corner_radius);
 
         mRoundedTop = new GradientDrawable();
-        mRoundedTop.setColor(Themes.getAttrColor(context, R.attr.popupColorPrimary));
         mRoundedTop.setCornerRadii(new float[] { mOutlineRadius, mOutlineRadius, mOutlineRadius,
                 mOutlineRadius, 0, 0, 0, 0});
 
         mRoundedBottom = new GradientDrawable();
-        mRoundedBottom.setColor(Themes.getAttrColor(context, R.attr.popupColorPrimary));
         mRoundedBottom.setCornerRadii(new float[] { 0, 0, 0, 0, mOutlineRadius, mOutlineRadius,
                 mOutlineRadius, mOutlineRadius});
 
+        int primaryColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
+        int secondaryColor = Themes.getAttrColor(context, R.attr.popupColorSecondary);
+        ArgbEvaluator argb = new ArgbEvaluator();
+        mColors = new int[MAX_NUM_CHILDREN];
+        // Interpolate between the two colors, exclusive.
+        float step = 1f / (MAX_NUM_CHILDREN + 1);
+        for (int i = 0; i < mColors.length; ++i) {
+            mColors[i] = (int) argb.evaluate((i + 1) * step, primaryColor, secondaryColor);
+        }
     }
 
     public ArrowPopup(Context context, AttributeSet attrs) {
@@ -187,6 +204,7 @@
 
         int numVisibleShortcut = 0;
         View lastView = null;
+        int numVisibleChild = 0;
         for (int i = 0; i < count; i++) {
             View view = getChildAt(i);
             boolean isShortcut = view instanceof DeepShortcutView;
@@ -207,16 +225,42 @@
                             view.setBackground(mRoundedTop);
                         } else if (numVisibleShortcut == (totalVisibleShortcuts - 1)) {
                             view.setBackground(mRoundedBottom);
+                        } else {
+                            view.setBackgroundResource(R.drawable.middle_item_primary);
                         }
                         numVisibleShortcut++;
                     }
                 }
+
+                int color = mColors[numVisibleChild % mColors.length];
+                setChildColor(view, color);
+
+                // Arrow color matches the first child or the last child.
+                if (!mIsAboveIcon && numVisibleChild == 0) {
+                    mArrowColor = color;
+                } else if (mIsAboveIcon) {
+                    mArrowColor = color;
+                }
+
+                numVisibleChild++;
             }
         }
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
     }
 
     /**
+     * Sets the background color of the child.
+     */
+    protected void setChildColor(View view, int color) {
+        Drawable bg = view.getBackground();
+        if (bg instanceof GradientDrawable) {
+            ((GradientDrawable) bg.mutate()).setColor(color);
+        } else if (bg instanceof ColorDrawable) {
+            ((ColorDrawable) bg.mutate()).setColor(color);
+        }
+    }
+
+    /**
      * Shows the popup at the desired location, optionally reversing the children.
      * @param viewsToFlip number of views from the top to to flip in case of reverse order
      */
@@ -293,7 +337,7 @@
                     mOutlineRadius, getMeasuredWidth(), getMeasuredHeight(),
                     mArrowOffsetHorizontal, -mArrowOffsetVertical,
                     !mIsAboveIcon, mIsLeftAligned,
-                    Themes.getAttrColor(getContext(), R.attr.popupColorPrimary)));
+                    mArrowColor));
             mArrow.setElevation(getElevation());
         }
 
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 4087f49..c282ae8 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -60,6 +60,7 @@
 import com.android.launcher3.notification.NotificationInfo;
 import com.android.launcher3.notification.NotificationItemView;
 import com.android.launcher3.notification.NotificationKeyData;
+import com.android.launcher3.notification.NotificationMainView;
 import com.android.launcher3.popup.PopupDataProvider.PopupDataChangeListener;
 import com.android.launcher3.shortcuts.DeepShortcutView;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
@@ -170,6 +171,14 @@
         return false;
     }
 
+    @Override
+    protected void setChildColor(View v, int color) {
+        super.setChildColor(v, color);
+        if (v.getId() == R.id.notification_container && mNotificationItemView != null) {
+            mNotificationItemView.updateBackgroundColor(color);
+        }
+    }
+
     /**
      * Returns true if we can show the container.
      */
@@ -333,19 +342,11 @@
     private void updateHiddenShortcuts() {
         int allowedCount = mNotificationItemView != null
                 ? MAX_SHORTCUTS_IF_NOTIFICATIONS : MAX_SHORTCUTS;
-        int originalHeight = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_height);
-        int itemHeight = mNotificationItemView != null ?
-                getResources().getDimensionPixelSize(R.dimen.bg_popup_item_condensed_height)
-                : originalHeight;
-        float iconScale = ((float) itemHeight) / originalHeight;
 
         int total = mShortcuts.size();
         for (int i = 0; i < total; i++) {
             DeepShortcutView view = mShortcuts.get(i);
             view.setVisibility(i >= allowedCount ? GONE : VISIBLE);
-            view.getLayoutParams().height = itemHeight;
-            view.getIconView().setScaleX(iconScale);
-            view.getIconView().setScaleY(iconScale);
         }
     }
 
@@ -567,6 +568,7 @@
                 // No more notifications, remove the notification views and expand all shortcuts.
                 mNotificationItemView.removeAllViews();
                 mNotificationItemView = null;
+                mNotificationContainer.setVisibility(GONE);
                 updateHiddenShortcuts();
                 assignMarginsAndBackgrounds();
             } else {