Adding support for customiting the animation in PropertySetter

Bug: 233223446
Test: Manual
Change-Id: I53fc39fa4871c9ea5b6eaf324ec1054140ccc292
diff --git a/src/com/android/launcher3/anim/AnimatedPropertySetter.java b/src/com/android/launcher3/anim/AnimatedPropertySetter.java
new file mode 100644
index 0000000..e5f5e7c
--- /dev/null
+++ b/src/com/android/launcher3/anim/AnimatedPropertySetter.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2022 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.launcher3.anim;
+
+import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.graphics.drawable.ColorDrawable;
+import android.util.FloatProperty;
+import android.util.IntProperty;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+import java.util.function.Consumer;
+
+/**
+ * Extension of {@link PropertySetter} which applies the property through an animation
+ */
+public class AnimatedPropertySetter extends PropertySetter {
+
+    protected final AnimatorSet mAnim = new AnimatorSet();
+    protected ValueAnimator mProgressAnimator;
+
+    @Override
+    public Animator setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
+        if (view == null || view.getAlpha() == alpha) {
+            return NO_OP;
+        }
+        ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
+        anim.addListener(new AlphaUpdateListener(view));
+        anim.setInterpolator(interpolator);
+        add(anim);
+        return anim;
+    }
+
+    @Override
+    public Animator setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
+        if (view == null || (view.getBackground() instanceof ColorDrawable
+                && ((ColorDrawable) view.getBackground()).getColor() == color)) {
+            return NO_OP;
+        }
+        ObjectAnimator anim = ObjectAnimator.ofArgb(view, VIEW_BACKGROUND_COLOR, color);
+        anim.setInterpolator(interpolator);
+        add(anim);
+        return anim;
+    }
+
+    @Override
+    public <T> Animator setFloat(T target, FloatProperty<T> property, float value,
+            TimeInterpolator interpolator) {
+        if (property.get(target) == value) {
+            return NO_OP;
+        }
+        Animator anim = ObjectAnimator.ofFloat(target, property, value);
+        anim.setInterpolator(interpolator);
+        add(anim);
+        return anim;
+    }
+
+    @Override
+    public <T> Animator setInt(T target, IntProperty<T> property, int value,
+            TimeInterpolator interpolator) {
+        if (property.get(target) == value) {
+            return NO_OP;
+        }
+        Animator anim = ObjectAnimator.ofInt(target, property, value);
+        anim.setInterpolator(interpolator);
+        add(anim);
+        return anim;
+    }
+
+
+    /**
+     * Adds a callback to be run on every frame of the animation
+     */
+    public void addOnFrameCallback(Runnable runnable) {
+        addOnFrameListener(anim -> runnable.run());
+    }
+
+    /**
+     * Adds a listener to be run on every frame of the animation
+     */
+    public void addOnFrameListener(ValueAnimator.AnimatorUpdateListener listener) {
+        if (mProgressAnimator == null) {
+            mProgressAnimator = ValueAnimator.ofFloat(0, 1);
+        }
+
+        mProgressAnimator.addUpdateListener(listener);
+    }
+
+    @Override
+    public void addEndListener(Consumer<Boolean> listener) {
+        if (mProgressAnimator == null) {
+            mProgressAnimator = ValueAnimator.ofFloat(0, 1);
+        }
+        mProgressAnimator.addListener(AnimatorListeners.forEndCallback(listener));
+    }
+
+    /**
+     * @see AnimatorSet#addListener(AnimatorListener)
+     */
+    public void addListener(Animator.AnimatorListener listener) {
+        mAnim.addListener(listener);
+    }
+
+    @Override
+    public void add(Animator a) {
+        mAnim.play(a);
+    }
+
+    /**
+     * Creates and returns the underlying AnimatorSet
+     */
+    @NonNull
+    public AnimatorSet buildAnim() {
+        // Add progress animation to the end, so that frame callback is called after all the other
+        // animation update.
+        if (mProgressAnimator != null) {
+            add(mProgressAnimator);
+            mProgressAnimator = null;
+        }
+        return mAnim;
+    }
+}
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 1300ce7..7316420 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -15,24 +15,18 @@
  */
 package com.android.launcher3.anim;
 
-import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
 import static com.android.launcher3.anim.AnimatorPlaybackController.addAnimationHoldersRecur;
 
 import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
-import android.graphics.drawable.ColorDrawable;
 import android.util.FloatProperty;
-import android.util.IntProperty;
-import android.view.View;
 
 import com.android.launcher3.anim.AnimatorPlaybackController.Holder;
 
 import java.util.ArrayList;
-import java.util.function.Consumer;
 
 /**
  * Utility class to keep track of a running animation.
@@ -43,17 +37,13 @@
  *
  * TODO: Find a better name
  */
-public class PendingAnimation implements PropertySetter {
+public class PendingAnimation extends AnimatedPropertySetter {
 
     private final ArrayList<Holder> mAnimHolders = new ArrayList<>();
-    private final AnimatorSet mAnim;
     private final long mDuration;
 
-    private ValueAnimator mProgressAnimator;
-
     public PendingAnimation(long  duration) {
         mDuration = duration;
-        mAnim = new AnimatorSet();
     }
 
     public long getDuration() {
@@ -68,6 +58,7 @@
         add(anim, springProperty);
     }
 
+    @Override
     public void add(Animator anim) {
         add(anim, SpringProperty.DEFAULT);
     }
@@ -84,39 +75,6 @@
         mAnim.setInterpolator(interpolator);
     }
 
-    @Override
-    public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
-        if (view == null || view.getAlpha() == alpha) {
-            return;
-        }
-        ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
-        anim.addListener(new AlphaUpdateListener(view));
-        anim.setInterpolator(interpolator);
-        add(anim);
-    }
-
-    @Override
-    public void setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
-        if (view == null || (view.getBackground() instanceof ColorDrawable
-                && ((ColorDrawable) view.getBackground()).getColor() == color)) {
-            return;
-        }
-        ObjectAnimator anim = ObjectAnimator.ofArgb(view, VIEW_BACKGROUND_COLOR, color);
-        anim.setInterpolator(interpolator);
-        add(anim);
-    }
-
-    @Override
-    public <T> void setFloat(T target, FloatProperty<T> property, float value,
-            TimeInterpolator interpolator) {
-        if (property.get(target) == value) {
-            return;
-        }
-        Animator anim = ObjectAnimator.ofFloat(target, property, value);
-        anim.setDuration(mDuration).setInterpolator(interpolator);
-        add(anim);
-    }
-
     public <T> void addFloat(T target, FloatProperty<T> property, float from, float to,
             TimeInterpolator interpolator) {
         Animator anim = ObjectAnimator.ofFloat(target, property, from, to);
@@ -124,57 +82,16 @@
         add(anim);
     }
 
-    @Override
-    public <T> void setInt(T target, IntProperty<T> property, int value,
-            TimeInterpolator interpolator) {
-        if (property.get(target) == value) {
-            return;
-        }
-        Animator anim = ObjectAnimator.ofInt(target, property, value);
-        anim.setInterpolator(interpolator);
-        add(anim);
-    }
-
-    /**
-     * Adds a callback to be run on every frame of the animation
-     */
-    public void addOnFrameCallback(Runnable runnable) {
-        addOnFrameListener(anim -> runnable.run());
-    }
-
-    /**
-     * Adds a listener to be run on every frame of the animation
-     */
-    public void addOnFrameListener(ValueAnimator.AnimatorUpdateListener listener) {
-        if (mProgressAnimator == null) {
-            mProgressAnimator = ValueAnimator.ofFloat(0, 1);
-        }
-
-        mProgressAnimator.addUpdateListener(listener);
-    }
-
-    /**
-     * @see AnimatorSet#addListener(AnimatorListener)
-     */
-    public void addListener(Animator.AnimatorListener listener) {
-        mAnim.addListener(listener);
-    }
-
     /**
      * Creates and returns the underlying AnimatorSet
      */
+    @Override
     public AnimatorSet buildAnim() {
-        // Add progress animation to the end, so that frame callback is called after all the other
-        // animation update.
-        if (mProgressAnimator != null) {
-            add(mProgressAnimator);
-            mProgressAnimator = null;
-        }
         if (mAnimHolders.isEmpty()) {
             // Add a placeholder animation to that the duration is respected
             add(ValueAnimator.ofFloat(0, 1).setDuration(mDuration));
         }
-        return mAnim;
+        return super.buildAnim();
     }
 
     /**
@@ -183,14 +100,4 @@
     public AnimatorPlaybackController createPlaybackController() {
         return new AnimatorPlaybackController(buildAnim(), mDuration, mAnimHolders);
     }
-
-    /**
-     * Add a listener of receiving the success/failure callback in the end.
-     */
-    public void addEndListener(Consumer<Boolean> listener) {
-        if (mProgressAnimator == null) {
-            mProgressAnimator = ValueAnimator.ofFloat(0, 1);
-        }
-        mProgressAnimator.addListener(AnimatorListeners.forEndCallback(listener));
-    }
 }
diff --git a/src/com/android/launcher3/anim/PropertySetter.java b/src/com/android/launcher3/anim/PropertySetter.java
index 8d77b4b..d2207f6 100644
--- a/src/com/android/launcher3/anim/PropertySetter.java
+++ b/src/com/android/launcher3/anim/PropertySetter.java
@@ -17,57 +17,94 @@
 package com.android.launcher3.anim;
 
 import android.animation.Animator;
+import android.animation.AnimatorSet;
 import android.animation.TimeInterpolator;
 import android.util.FloatProperty;
 import android.util.IntProperty;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+
+import java.util.function.Consumer;
+
 /**
  * Utility class for setting a property with or without animation
  */
-public interface PropertySetter {
+public abstract class PropertySetter {
 
-    PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter() { };
+    public static final PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter() {
+
+        @Override
+        public void add(Animator animatorSet) {
+            animatorSet.setDuration(0);
+            animatorSet.start();
+        }
+    };
+
+    protected static final AnimatorSet NO_OP = new AnimatorSet();
 
     /**
      * Sets the view alpha using the provided interpolator.
      * Unlike {@link #setFloat}, this also updates the visibility of the view as alpha changes
      * between zero and non-zero.
      */
-    default void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
+    @NonNull
+    public Animator setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
         if (view != null) {
             view.setAlpha(alpha);
             AlphaUpdateListener.updateVisibility(view);
         }
+        return NO_OP;
     }
 
     /**
      * Sets the background color of the provided view using the provided interpolator.
      */
-    default void setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
+    @NonNull
+    public Animator setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
         if (view != null) {
             view.setBackgroundColor(color);
         }
+        return NO_OP;
     }
 
     /**
      * Updates the float property of the target using the provided interpolator
      */
-    default <T> void setFloat(T target, FloatProperty<T> property, float value,
+    @NonNull
+    public <T> Animator setFloat(T target, FloatProperty<T> property, float value,
             TimeInterpolator interpolator) {
         property.setValue(target, value);
+        return NO_OP;
     }
 
     /**
      * Updates the int property of the target using the provided interpolator
      */
-    default <T> void setInt(T target, IntProperty<T> property, int value,
+    @NonNull
+    public <T> Animator setInt(T target, IntProperty<T> property, int value,
             TimeInterpolator interpolator) {
         property.setValue(target, value);
+        return NO_OP;
     }
 
-    default void add(Animator animatorSet) {
-        animatorSet.setDuration(0);
-        animatorSet.start();
+    /**
+     * Runs the animation as part of setting the property
+     */
+    public abstract void add(Animator animatorSet);
+
+    /**
+     * Add a listener of receiving the success/failure callback in the end.
+     */
+    public void addEndListener(Consumer<Boolean> listener) {
+        listener.accept(true);
+    }
+
+    /**
+     * Creates and returns the AnimatorSet that can be run to apply the properties
+     */
+    @NonNull
+    public AnimatorSet buildAnim() {
+        return NO_OP;
     }
 }