From 52bbef9d94575185d05a6ed894230f93e7d36e29 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 19 May 2022 09:27:26 -0700 Subject: [PATCH] Adding support for customiting the animation in PropertySetter Bug: 233223446 Test: Manual Change-Id: I53fc39fa4871c9ea5b6eaf324ec1054140ccc292 --- .../anim/AnimatedPropertySetter.java | 144 ++++++++++++++++++ .../launcher3/anim/PendingAnimation.java | 101 +----------- .../launcher3/anim/PropertySetter.java | 55 +++++-- 3 files changed, 194 insertions(+), 106 deletions(-) create mode 100644 src/com/android/launcher3/anim/AnimatedPropertySetter.java diff --git a/src/com/android/launcher3/anim/AnimatedPropertySetter.java b/src/com/android/launcher3/anim/AnimatedPropertySetter.java new file mode 100644 index 0000000000..e5f5e7c44b --- /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 Animator setFloat(T target, FloatProperty 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 Animator setInt(T target, IntProperty 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 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 1300ce7f9c..7316420b12 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 @@ import java.util.function.Consumer; * * TODO: Find a better name */ -public class PendingAnimation implements PropertySetter { +public class PendingAnimation extends AnimatedPropertySetter { private final ArrayList 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 @@ public class PendingAnimation implements PropertySetter { add(anim, springProperty); } + @Override public void add(Animator anim) { add(anim, SpringProperty.DEFAULT); } @@ -84,39 +75,6 @@ public class PendingAnimation implements PropertySetter { 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 void setFloat(T target, FloatProperty 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 void addFloat(T target, FloatProperty property, float from, float to, TimeInterpolator interpolator) { Animator anim = ObjectAnimator.ofFloat(target, property, from, to); @@ -124,57 +82,16 @@ public class PendingAnimation implements PropertySetter { add(anim); } - @Override - public void setInt(T target, IntProperty 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 class PendingAnimation implements PropertySetter { 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 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 8d77b4ba8d..d2207f6351 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 void setFloat(T target, FloatProperty property, float value, + @NonNull + public Animator setFloat(T target, FloatProperty property, float value, TimeInterpolator interpolator) { property.setValue(target, value); + return NO_OP; } /** * Updates the int property of the target using the provided interpolator */ - default void setInt(T target, IntProperty property, int value, + @NonNull + public Animator setInt(T target, IntProperty 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 listener) { + listener.accept(true); + } + + /** + * Creates and returns the AnimatorSet that can be run to apply the properties + */ + @NonNull + public AnimatorSet buildAnim() { + return NO_OP; } }