Blocking alpha animation if the initial and final state for the animation
are both 0

Bug: 30739854
Change-Id: I4f7c579dc3f64a4fed60d7b2f8ecd5f359e165ec
diff --git a/src/com/android/launcher3/util/MultiStateAlphaController.java b/src/com/android/launcher3/util/MultiStateAlphaController.java
index 2a49361..956fc9e 100644
--- a/src/com/android/launcher3/util/MultiStateAlphaController.java
+++ b/src/com/android/launcher3/util/MultiStateAlphaController.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.util;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
@@ -33,6 +34,7 @@
     private final View mTargetView;
     private final float[] mAlphas;
     private final AccessibilityManager mAm;
+    private int mZeroAlphaListenerCount = 0;
 
     public MultiStateAlphaController(View view, int stateCount) {
         mTargetView = view;
@@ -44,12 +46,20 @@
 
     public void setAlphaAtIndex(float alpha, int index) {
         mAlphas[index] = alpha;
+        updateAlpha();
+    }
+
+    private void updateAlpha() {
+        // Only update the alpha if no zero-alpha animation is running.
+        if (mZeroAlphaListenerCount > 0) {
+            return;
+        }
         float finalAlpha = 1;
         for (float a : mAlphas) {
             finalAlpha = finalAlpha * a;
         }
         mTargetView.setAlpha(finalAlpha);
-        mTargetView.setVisibility(alpha > 0 ? View.VISIBLE
+        mTargetView.setVisibility(finalAlpha > 0 ? View.VISIBLE
                 : (mAm.isEnabled() ? View.GONE : View.INVISIBLE));
     }
 
@@ -58,9 +68,11 @@
      * to {@param finalAlpha}. Alphas at other index are not affected.
      */
     public Animator animateAlphaAtIndex(float finalAlpha, final int index) {
+        final ValueAnimator anim;
+
         if (Float.compare(finalAlpha, mAlphas[index]) == 0) {
             // Return a dummy animator to avoid null checks.
-            return ValueAnimator.ofFloat(0, 0);
+            anim = ValueAnimator.ofFloat(0, 0);
         } else {
             ValueAnimator animator = ValueAnimator.ofFloat(mAlphas[index], finalAlpha);
             animator.addUpdateListener(new AnimatorUpdateListener() {
@@ -70,7 +82,38 @@
                     setAlphaAtIndex(value, index);
                 }
             });
-            return animator;
+            anim = animator;
+        }
+
+        if (Float.compare(finalAlpha, 0f) == 0) {
+            // In case when any channel is animating to 0, and the current alpha is also 0, do not
+            // update alpha of the target view while the animation is running.
+            // We special case '0' because if any channel is set to 0, values of other
+            // channels do not matter.
+            anim.addListener(new ZeroAlphaAnimatorListener());
+        }
+        return anim;
+    }
+
+    private class ZeroAlphaAnimatorListener extends AnimatorListenerAdapter {
+
+        private boolean mStartedAtZero = false;
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            mStartedAtZero = Float.compare(mTargetView.getAlpha(), 0f) == 0;
+            if (mStartedAtZero) {
+                mZeroAlphaListenerCount++;
+                mTargetView.setAlpha(0);
+            }
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (mStartedAtZero) {
+                mZeroAlphaListenerCount--;
+                updateAlpha();
+            }
         }
     }
 }