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

Commit e89a83b6 authored by Tracy Zhou's avatar Tracy Zhou
Browse files

Track LauncherState, RecentsAnimation, resumed state for task bar in one place

TODO:
- Consider delaying animating task bar to stashed towards all apps state until user releasing their finger (tho in this change heuristic is applied for stashing and unstashing respectively)
- Further consolidate some animation logic

Bug: 204220602
Test: manual

Change-Id: I58b4d035fcf65a9f5c68e69c129eae95b89b1c4a
parent f37d7a21
Loading
Loading
Loading
Loading
+10 −241
Original line number Original line Diff line number Diff line
@@ -15,18 +15,10 @@
 */
 */
package com.android.launcher3.taskbar;
package com.android.launcher3.taskbar;


import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
import static com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_DURATION;
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;


import android.animation.Animator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.ColorInt;
import android.annotation.ColorInt;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.RemoteException;
@@ -44,28 +36,17 @@ import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
import com.android.quickstep.RecentsAnimationController;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;


import java.util.Arrays;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.Stream;


/**
/**
@@ -77,82 +58,15 @@ public class LauncherTaskbarUIController extends TaskbarUIController {


    private final BaseQuickstepLauncher mLauncher;
    private final BaseQuickstepLauncher mLauncher;


    private final AnimatedFloat mIconAlignmentForResumedState =
            new AnimatedFloat(this::onIconAlignmentRatioChanged);
    private final AnimatedFloat mIconAlignmentForGestureState =
            new AnimatedFloat(this::onIconAlignmentRatioChanged);
    private final AnimatedFloat mIconAlignmentForLauncherState =
            new AnimatedFloat(this::onIconAlignmentRatioChangedForStateTransition);

    private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
    private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
            this::onStashedInAppChanged;
            this::onStashedInAppChanged;


    private final StateManager.StateListener<LauncherState> mStateListener =
            new StateManager.StateListener<LauncherState>() {
                private Animator mAnimator;

                @Override
                public void onStateTransitionStart(LauncherState toState) {
                    // Stash animation from going to launcher should be already handled in
                    // createAnimToLauncher.
                    TaskbarStashController controller = mControllers.taskbarStashController;
                    long duration = TASKBAR_STASH_DURATION;
                    controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
                            toState.isTaskbarStashed());
                    Animator stashAnimator = controller.applyStateWithoutStart(duration);
                    if (stashAnimator != null) {
                        if (mAnimator != null) {
                            mAnimator.cancel();
                        }
                        PendingAnimation pendingAnimation = new PendingAnimation(duration);
                        pendingAnimation.add(stashAnimator);
                        pendingAnimation.setFloat(mIconAlignmentForLauncherState,
                                AnimatedFloat.VALUE, toState.isTaskbarStashed() ? 0 : 1,
                                FAST_OUT_SLOW_IN);
                        pendingAnimation.addListener(new AnimatorListenerAdapter() {
                            @Override
                            public void onAnimationStart(Animator animator) {
                                mTargetStateOverrideForStateTransition = toState;
                                // Copy hotseat alpha over to taskbar icons
                                mIconAlphaForHome.setValue(mLauncher.getHotseat().getIconsAlpha());
                                mLauncher.getHotseat().setIconsAlpha(0);
                            }

                            @Override
                            public void onAnimationEnd(Animator animator) {
                                if (toState.isTaskbarStashed()) {
                                    // Reset hotseat alpha to default
                                    mLauncher.getHotseat().setIconsAlpha(1);
                                }
                                mTargetStateOverrideForStateTransition = null;
                                mAnimator = null;
                            }
                        });
                        mAnimator = pendingAnimation.buildAnim();
                        mAnimator.start();
                    }
                }

                @Override
                public void onStateTransitionComplete(LauncherState finalState) {
                    TaskbarStashController controller = mControllers.taskbarStashController;
                    controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
                            finalState.isTaskbarStashed());
                    controller.applyState();
                }
            };

    // Initialized in init.
    // Initialized in init.
    private TaskbarControllers mControllers;
    private TaskbarControllers mControllers;
    private AnimatedFloat mTaskbarBackgroundAlpha;
    private AnimatedFloat mTaskbarOverrideBackgroundAlpha;
    private AnimatedFloat mTaskbarOverrideBackgroundAlpha;
    private AlphaProperty mIconAlphaForHome;
    private boolean mIsAnimatingToLauncherViaResume;
    private boolean mIsAnimatingToLauncherViaGesture;
    private TaskbarKeyguardController mKeyguardController;
    private TaskbarKeyguardController mKeyguardController;

    private final TaskbarLauncherStateController
    private LauncherState mTargetStateOverride = null;
            mTaskbarLauncherStateController = new TaskbarLauncherStateController();
    private LauncherState mTargetStateOverrideForStateTransition = null;


    private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener =
    private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener =
            new DeviceProfile.OnDeviceProfileChangeListener() {
            new DeviceProfile.OnDeviceProfileChangeListener() {
@@ -171,37 +85,26 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
    protected void init(TaskbarControllers taskbarControllers) {
    protected void init(TaskbarControllers taskbarControllers) {
        mControllers = taskbarControllers;
        mControllers = taskbarControllers;


        mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController
        mTaskbarLauncherStateController.init(mControllers, mLauncher);
                .getTaskbarBackgroundAlpha();
        mTaskbarOverrideBackgroundAlpha = mControllers.taskbarDragLayerController
        mTaskbarOverrideBackgroundAlpha = mControllers.taskbarDragLayerController
                .getOverrideBackgroundAlpha();
                .getOverrideBackgroundAlpha();


        MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha();
        mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);

        mLauncher.setTaskbarUIController(this);
        mLauncher.setTaskbarUIController(this);
        mKeyguardController = taskbarControllers.taskbarKeyguardController;
        mKeyguardController = taskbarControllers.taskbarKeyguardController;


        onLauncherResumedOrPaused(mLauncher.hasBeenResumed(), true /* fromInit */);
        onLauncherResumedOrPaused(mLauncher.hasBeenResumed(), true /* fromInit */);
        mIconAlignmentForResumedState.finishAnimation();
        onIconAlignmentRatioChanged();


        onStashedInAppChanged(mLauncher.getDeviceProfile());
        onStashedInAppChanged(mLauncher.getDeviceProfile());
        mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
        mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
        mLauncher.getStateManager().addStateListener(mStateListener);
        mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener);
        mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener);
    }
    }


    @Override
    @Override
    protected void onDestroy() {
    protected void onDestroy() {
        onLauncherResumedOrPaused(false);
        onLauncherResumedOrPaused(false);
        mIconAlignmentForResumedState.finishAnimation();
        mTaskbarLauncherStateController.onDestroy();
        mIconAlignmentForGestureState.finishAnimation();
        mIconAlignmentForLauncherState.finishAnimation();


        mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
        mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
        mLauncher.getStateManager().removeStateListener(mStateListener);
        mLauncher.getHotseat().setIconsAlpha(1f);
        mLauncher.setTaskbarUIController(null);
        mLauncher.setTaskbarUIController(null);
        mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener);
        mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener);
        updateTaskTransitionSpec(true);
        updateTaskTransitionSpec(true);
@@ -209,11 +112,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {


    @Override
    @Override
    protected boolean isTaskbarTouchable() {
    protected boolean isTaskbarTouchable() {
        return !isAnimatingToLauncher();
        return !mTaskbarLauncherStateController.isAnimatingToLauncher();
    }

    private boolean isAnimatingToLauncher() {
        return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
    }
    }


    @Override
    @Override
@@ -240,24 +139,9 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
            }
            }
        }
        }


        long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION;
        mTaskbarLauncherStateController.updateStateForFlag(FLAG_RESUMED, isResumed);
        if (fromInit) {
        mTaskbarLauncherStateController.applyState(
            // Since we are creating the starting state, we don't have a state to animate from, so
                fromInit ? 0 : QuickstepTransitionManager.CONTENT_ALPHA_DURATION);
            // set our state immediately.
            duration = 0;
        }
        ObjectAnimator anim = mIconAlignmentForResumedState.animateToValue(
                getCurrentIconAlignmentRatio(), isResumed ? 1 : 0)
                .setDuration(duration);

        anim.addListener(AnimatorListeners.forEndCallback(
                () -> mIsAnimatingToLauncherViaResume = false));
        anim.start();
        mIsAnimatingToLauncherViaResume = isResumed;

        TaskbarStashController stashController = mControllers.taskbarStashController;
        stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
        stashController.applyState(duration);
    }
    }


    /**
    /**
@@ -268,77 +152,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
     */
     */
    public Animator createAnimToLauncher(@NonNull LauncherState toState,
    public Animator createAnimToLauncher(@NonNull LauncherState toState,
            @NonNull RecentsAnimationCallbacks callbacks, long duration) {
            @NonNull RecentsAnimationCallbacks callbacks, long duration) {
        AnimatorSet animatorSet = new AnimatorSet();
        return mTaskbarLauncherStateController.createAnimToLauncher(toState, callbacks, duration);
        TaskbarStashController stashController = mControllers.taskbarStashController;
        stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
                toState.isTaskbarStashed());
        if (toState.isTaskbarStashed()) {
            animatorSet.play(stashController.applyStateWithoutStart(duration));
        } else {
            animatorSet.play(mIconAlignmentForGestureState
                    .animateToValue(1)
                    .setDuration(duration));
        }
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animator) {
                mTargetStateOverride = null;
                animator.removeListener(this);
            }

            @Override
            public void onAnimationStart(Animator animator) {
                mTargetStateOverride = toState;
                mIsAnimatingToLauncherViaGesture = true;
                stashController.updateStateForFlag(FLAG_IN_APP, false);
                stashController.applyState(duration);
            }
        });

        TaskBarRecentsAnimationListener listener = new TaskBarRecentsAnimationListener(callbacks);
        callbacks.addListener(listener);
        RecentsView recentsView = mLauncher.getOverviewPanel();
        recentsView.setTaskLaunchListener(() -> {
            listener.endGestureStateOverride(true);
            callbacks.removeListener(listener);
        });

        return animatorSet;
    }

    private float getCurrentIconAlignmentRatio() {
        return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value);
    }

    private float getCurrentIconAlignmentRatioForLauncherState() {
        return mIconAlignmentForLauncherState.value;
    }

    private void onIconAlignmentRatioChangedForStateTransition() {
        onIconAlignmentRatioChanged(
                mTargetStateOverrideForStateTransition != null
                        ? mTargetStateOverrideForStateTransition
                        : mLauncher.getStateManager().getState(),
                this::getCurrentIconAlignmentRatioForLauncherState);
    }

    private void onIconAlignmentRatioChanged() {
        onIconAlignmentRatioChanged(mTargetStateOverride != null ? mTargetStateOverride
                : mLauncher.getStateManager().getState(), this::getCurrentIconAlignmentRatio);
    }

    private void onIconAlignmentRatioChanged(LauncherState state,
            Supplier<Float> alignmentSupplier) {
        if (mControllers == null) {
            return;
        }
        float alignment = alignmentSupplier.get();
        mControllers.taskbarViewController.setLauncherIconAlignment(
                alignment, mLauncher.getDeviceProfile());

        mTaskbarBackgroundAlpha.updateValue(1 - alignment);

        setIconAlpha(state, alignment);
    }
    }


    /**
    /**
@@ -358,20 +172,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
        return mControllers.taskbarActivityContext.getDragLayer();
        return mControllers.taskbarActivityContext.getDragLayer();
    }
    }


    private void setIconAlpha(LauncherState state, float progress) {
        if ((state.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
            // If the hotseat icons are visible, then switch taskbar in last frame
            setTaskbarViewVisible(progress < 1);
        } else {
            mIconAlphaForHome.setValue(1 - progress);
        }
    }

    private void setTaskbarViewVisible(boolean isVisible) {
        mIconAlphaForHome.setValue(isVisible ? 1 : 0);
        mLauncher.getHotseat().setIconsAlpha(isVisible ? 0f : 1f);
    }

    @Override
    @Override
    protected void onStashedInAppChanged() {
    protected void onStashedInAppChanged() {
        onStashedInAppChanged(mLauncher.getDeviceProfile());
        onStashedInAppChanged(mLauncher.getDeviceProfile());
@@ -451,35 +251,4 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
        mLauncher.logAppLaunch(mControllers.taskbarActivityContext.getStatsLogManager(), item,
        mLauncher.logAppLaunch(mControllers.taskbarActivityContext.getStatsLogManager(), item,
                instanceId);
                instanceId);
    }
    }

    private final class TaskBarRecentsAnimationListener implements RecentsAnimationListener {
        private final RecentsAnimationCallbacks mCallbacks;

        TaskBarRecentsAnimationListener(RecentsAnimationCallbacks callbacks) {
            mCallbacks = callbacks;
        }

        @Override
        public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
            endGestureStateOverride(true);
        }

        @Override
        public void onRecentsAnimationFinished(RecentsAnimationController controller) {
            endGestureStateOverride(!controller.getFinishTargetIsLauncher());
        }

        private void endGestureStateOverride(boolean finishedToApp) {
            mCallbacks.removeListener(this);
            mIsAnimatingToLauncherViaGesture = false;

            mIconAlignmentForGestureState
                    .animateToValue(0)
                    .start();

            TaskbarStashController controller = mControllers.taskbarStashController;
            controller.updateStateForFlag(FLAG_IN_APP, finishedToApp);
            controller.applyState();
        }
    }
}
}
+395 −0

File added.

Preview size limit exceeded, changes collapsed.

+12 −1
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.view.View;
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.anim.AlphaUpdateListener;


import java.util.Arrays;
import java.util.Arrays;
import java.util.function.Consumer;


/**
/**
 * Utility class to handle separating a single value as a factor of multiple values
 * Utility class to handle separating a single value as a factor of multiple values
@@ -85,6 +86,8 @@ public class MultiValueAlpha {
        // Factor of all other alpha channels, only valid if mMyMask is present in mValidMask.
        // Factor of all other alpha channels, only valid if mMyMask is present in mValidMask.
        private float mOthers = 1;
        private float mOthers = 1;


        private Consumer<Float> mConsumer;

        AlphaProperty(int myMask) {
        AlphaProperty(int myMask) {
            mMyMask = myMask;
            mMyMask = myMask;
        }
        }
@@ -109,16 +112,24 @@ public class MultiValueAlpha {
            mValidMask = mMyMask;
            mValidMask = mMyMask;
            mValue = value;
            mValue = value;


            mView.setAlpha(mOthers * mValue);
            final float alpha = mOthers * mValue;
            mView.setAlpha(alpha);
            if (mUpdateVisibility) {
            if (mUpdateVisibility) {
                AlphaUpdateListener.updateVisibility(mView);
                AlphaUpdateListener.updateVisibility(mView);
            }
            }
            if (mConsumer != null) {
                mConsumer.accept(mValue);
            }
        }
        }


        public float getValue() {
        public float getValue() {
            return mValue;
            return mValue;
        }
        }


        public void setConsumer(Consumer<Float> consumer) {
            mConsumer = consumer;
        }

        @Override
        @Override
        public String toString() {
        public String toString() {
            return Float.toString(mValue);
            return Float.toString(mValue);