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

Commit b871c13e authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Adding a compat implementation for playback control on AnimatorSet

Change-Id: I9f01fc319341cf2499fffb59521d32c2c81eba45
parent 3e3f44c3
Loading
Loading
Loading
Loading
+7 −36
Original line number Diff line number Diff line
@@ -16,30 +16,22 @@

package com.android.launcher3;

import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.Range;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;

import com.android.launcher3.compat.AnimatorSetCompat;
import com.android.launcher3.util.TouchController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Detects pinches and animates the Workspace to/from overview mode.
 */
@TargetApi(Build.VERSION_CODES.O)
public class PinchToOverviewListener
        implements TouchController, OnScaleGestureListener, Runnable {

@@ -55,9 +47,8 @@ public class PinchToOverviewListener
    private Workspace mWorkspace = null;
    private boolean mPinchStarted = false;

    private AnimatorSet mCurrentAnimation;
    private AnimatorSetCompat mCurrentAnimation;
    private float mCurrentScale;
    private Range<Integer> mDurationRange;
    private boolean mShouldGoToFinalState;

    private LauncherState mToState;
@@ -109,14 +100,13 @@ public class PinchToOverviewListener
        }

        mToState = mLauncher.isInState(OVERVIEW) ? NORMAL : OVERVIEW;
        mCurrentAnimation = mLauncher.getStateManager()
                .createAnimationToNewWorkspace(mToState, this);
        mCurrentAnimation = AnimatorSetCompat.wrap(mLauncher.getStateManager()
                .createAnimationToNewWorkspace(mToState, this), OVERVIEW_TRANSITION_MS);
        mPinchStarted = true;
        mCurrentScale = 1;
        mDurationRange = Range.create(0, LauncherAnimUtils.OVERVIEW_TRANSITION_MS);
        mShouldGoToFinalState = false;

        dispatchOnStart(mCurrentAnimation);
        mCurrentAnimation.dispatchOnStart();
        return true;
    }

@@ -160,26 +150,7 @@ public class PinchToOverviewListener
        }

        // Move the transition animation to that duration.
        long playPosition = mDurationRange.clamp(
                (int) ((1 - animationFraction) * mDurationRange.getUpper()));
        mCurrentAnimation.setCurrentPlayTime(playPosition);

        mCurrentAnimation.setPlayFraction(1 - animationFraction);
        return true;
    }

    private void dispatchOnStart(Animator animator) {
        for (AnimatorListener l : nonNullList(animator.getListeners())) {
            l.onAnimationStart(animator);
        }

        if (animator instanceof AnimatorSet) {
            for (Animator anim : nonNullList(((AnimatorSet) animator).getChildAnimations())) {
                dispatchOnStart(anim);
            }
        }
    }

    private static <T> List<T> nonNullList(ArrayList<T> list) {
        return list == null ? Collections.<T>emptyList() : list;
    }
}
 No newline at end of file
+204 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.compat;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.animation.LinearInterpolator;

import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Compat implementation for various new APIs in {@link AnimatorSet}
 *
 * Note: The compat implementation does not support start delays on child animations or
 * sequential playbacks.
 */
public abstract class AnimatorSetCompat implements ValueAnimator.AnimatorUpdateListener {

    public static AnimatorSetCompat wrap(AnimatorSet anim, int duration) {
        if (Utilities.ATLEAST_OREO) {
            return new AnimatorSetCompatVO(anim, duration);
        } else {
            return new AnimatorSetCompatVL(anim, duration);
        }
    }

    private final ValueAnimator mAnimationPlayer;
    private final long mDuration;

    protected final AnimatorSet mAnim;

    protected float mCurrentFraction;

    protected AnimatorSetCompat(AnimatorSet anim, int duration) {
        mAnim = anim;
        mDuration = duration;

        mAnimationPlayer = ValueAnimator.ofFloat(0, 1);
        mAnimationPlayer.setInterpolator(new LinearInterpolator());
        mAnimationPlayer.addUpdateListener(this);
    }

    /**
     * Starts playing the animation forward from current position.
     */
    public void start() {
        mAnimationPlayer.setFloatValues(mCurrentFraction, 1);
        mAnimationPlayer.setDuration(clampDuration(1 - mCurrentFraction));
        mAnimationPlayer.addListener(new OnAnimationEndDispatcher());
        mAnimationPlayer.start();
    }

    /**
     * Starts playing the animation backwards from current position
     */
    public void reverse() {
        mAnimationPlayer.setFloatValues(mCurrentFraction, 0);
        mAnimationPlayer.setDuration(clampDuration(mCurrentFraction));
        mAnimationPlayer.addListener(new OnAnimationEndDispatcher());
        mAnimationPlayer.start();
    }

    /**
     * Sets the current animation position and updates all the child animators accordingly.
     */
    public abstract void setPlayFraction(float fraction);

    /**
     * @see Animator#addListener(AnimatorListener)
     */
    public void addListener(Animator.AnimatorListener listener) {
        mAnimationPlayer.addListener(listener);
    }

    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        setPlayFraction((float) valueAnimator.getAnimatedValue());
    }

    protected long clampDuration(float fraction) {
        float playPos = mDuration * fraction;
        if (playPos <= 0) {
            return 0;
        } else {
            return Math.min((long) playPos, mDuration);
        }
    }

    public void dispatchOnStart() {
        dispatchOnStartRecursively(mAnim);
    }

    private void dispatchOnStartRecursively(Animator animator) {
        for (AnimatorListener l : nonNullList(animator.getListeners())) {
            l.onAnimationStart(animator);
        }

        if (animator instanceof AnimatorSet) {
            for (Animator anim : nonNullList(((AnimatorSet) animator).getChildAnimations())) {
                dispatchOnStartRecursively(anim);
            }
        }
    }

    public static class AnimatorSetCompatVL extends AnimatorSetCompat {

        private final ValueAnimator[] mChildAnimations;

        private AnimatorSetCompatVL(AnimatorSet anim, int duration) {
            super(anim, duration);

            // Build animation list
            ArrayList<ValueAnimator> childAnims = new ArrayList<>();
            getAnimationsRecur(mAnim, childAnims);
            mChildAnimations = childAnims.toArray(new ValueAnimator[childAnims.size()]);
        }

        private void getAnimationsRecur(AnimatorSet anim, ArrayList<ValueAnimator> out) {
            long forceDuration = anim.getDuration();
            for (Animator child : anim.getChildAnimations()) {
                if (forceDuration > 0) {
                    child.setDuration(forceDuration);
                }
                if (child instanceof ValueAnimator) {
                    out.add((ValueAnimator) child);
                } else if (child instanceof AnimatorSet) {
                    getAnimationsRecur((AnimatorSet) child, out);
                } else {
                    throw new RuntimeException("Unknown animation type " + child);
                }
            }
        }

        @Override
        public void setPlayFraction(float fraction) {
            mCurrentFraction = fraction;
            long playPos = clampDuration(fraction);
            for (ValueAnimator anim : mChildAnimations) {
                anim.setCurrentPlayTime(Math.min(playPos, anim.getDuration()));
            }
        }

    }

    @TargetApi(Build.VERSION_CODES.O)
    private static class AnimatorSetCompatVO extends AnimatorSetCompat {

        private AnimatorSetCompatVO(AnimatorSet anim, int duration) {
            super(anim, duration);
        }

        @Override
        public void setPlayFraction(float fraction) {
            mCurrentFraction = fraction;
            mAnim.setCurrentPlayTime(clampDuration(fraction));
        }
    }

    private class OnAnimationEndDispatcher extends AnimationSuccessListener {

        @Override
        public void onAnimationSuccess(Animator animator) {
            dispatchOnEndRecursively(mAnim);
        }

        private void dispatchOnEndRecursively(Animator animator) {
            for (AnimatorListener l : nonNullList(animator.getListeners())) {
                l.onAnimationEnd(animator);
            }

            if (animator instanceof AnimatorSet) {
                for (Animator anim : nonNullList(((AnimatorSet) animator).getChildAnimations())) {
                    dispatchOnEndRecursively(anim);
                }
            }
        }
    }

    private static <T> List<T> nonNullList(ArrayList<T> list) {
        return list == null ? Collections.<T>emptyList() : list;
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ public class DragLayer extends InsettableFrameLayout {

    public void onAccessibilityStateChanged(boolean isAccessibilityEnabled) {
        mPinchListener = FeatureFlags.LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW || isAccessibilityEnabled
                || !Utilities.ATLEAST_OREO ? null : new PinchToOverviewListener(mLauncher);
                ? null : new PinchToOverviewListener(mLauncher);
    }

    public boolean isEventOverHotseat(MotionEvent ev) {