Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7a48aae authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Adding support for customiting the animation in PropertySetter" into tm-dev

parents af8b7d33 52bbef9d
Loading
Loading
Loading
Loading
+144 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+4 −97
Original line number Diff line number Diff line
@@ -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<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 @@ 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 <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 @@ public class PendingAnimation implements PropertySetter {
        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 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<Boolean> listener) {
        if (mProgressAnimator == null) {
            mProgressAnimator = ValueAnimator.ofFloat(0, 1);
        }
        mProgressAnimator.addListener(AnimatorListeners.forEndCallback(listener));
    }
}
+46 −9
Original line number Diff line number Diff line
@@ -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;
    }
}