diff options
author | Tracy Zhou <tracyzhou@google.com> | 2021-11-08 00:48:53 -0800 |
---|---|---|
committer | Tracy Zhou <tracyzhou@google.com> | 2021-11-09 23:46:03 -0800 |
commit | e89a83b65d54d89da1a323c3b69fa2ee12677fbf (patch) | |
tree | 9b7edfea514767343d7b27dd4c739bf2d65e9569 /quickstep/src | |
parent | f37d7a21f2b84cdcd995b21b186f08e9cab3210e (diff) |
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
Diffstat (limited to 'quickstep/src')
-rw-r--r-- | quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java | 251 | ||||
-rw-r--r-- | quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java | 395 |
2 files changed, 405 insertions, 241 deletions
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index aa312619bb..1c0c77328f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -15,18 +15,10 @@ */ package com.android.launcher3.taskbar; -import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; -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.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED; import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR; import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; import android.annotation.ColorInt; import android.graphics.Rect; import android.os.RemoteException; @@ -44,28 +36,17 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.QuickstepTransitionManager; import com.android.launcher3.R; 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.logging.InstanceId; import com.android.launcher3.logging.InstanceIdSequence; import com.android.launcher3.model.data.ItemInfoWithIcon; 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.quickstep.AnimatedFloat; 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.HashMap; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Stream; /** @@ -77,82 +58,15 @@ public class LauncherTaskbarUIController extends TaskbarUIController { 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 = 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. private TaskbarControllers mControllers; - private AnimatedFloat mTaskbarBackgroundAlpha; private AnimatedFloat mTaskbarOverrideBackgroundAlpha; - private AlphaProperty mIconAlphaForHome; - private boolean mIsAnimatingToLauncherViaResume; - private boolean mIsAnimatingToLauncherViaGesture; private TaskbarKeyguardController mKeyguardController; - - private LauncherState mTargetStateOverride = null; - private LauncherState mTargetStateOverrideForStateTransition = null; + private final TaskbarLauncherStateController + mTaskbarLauncherStateController = new TaskbarLauncherStateController(); private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener = new DeviceProfile.OnDeviceProfileChangeListener() { @@ -171,37 +85,26 @@ public class LauncherTaskbarUIController extends TaskbarUIController { protected void init(TaskbarControllers taskbarControllers) { mControllers = taskbarControllers; - mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController - .getTaskbarBackgroundAlpha(); + mTaskbarLauncherStateController.init(mControllers, mLauncher); mTaskbarOverrideBackgroundAlpha = mControllers.taskbarDragLayerController .getOverrideBackgroundAlpha(); - MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha(); - mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME); - mLauncher.setTaskbarUIController(this); mKeyguardController = taskbarControllers.taskbarKeyguardController; onLauncherResumedOrPaused(mLauncher.hasBeenResumed(), true /* fromInit */); - mIconAlignmentForResumedState.finishAnimation(); - onIconAlignmentRatioChanged(); onStashedInAppChanged(mLauncher.getDeviceProfile()); mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); - mLauncher.getStateManager().addStateListener(mStateListener); mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener); } @Override protected void onDestroy() { onLauncherResumedOrPaused(false); - mIconAlignmentForResumedState.finishAnimation(); - mIconAlignmentForGestureState.finishAnimation(); - mIconAlignmentForLauncherState.finishAnimation(); + mTaskbarLauncherStateController.onDestroy(); mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); - mLauncher.getStateManager().removeStateListener(mStateListener); - mLauncher.getHotseat().setIconsAlpha(1f); mLauncher.setTaskbarUIController(null); mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener); updateTaskTransitionSpec(true); @@ -209,11 +112,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { @Override protected boolean isTaskbarTouchable() { - return !isAnimatingToLauncher(); - } - - private boolean isAnimatingToLauncher() { - return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture; + return !mTaskbarLauncherStateController.isAnimatingToLauncher(); } @Override @@ -240,24 +139,9 @@ public class LauncherTaskbarUIController extends TaskbarUIController { } } - long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION; - if (fromInit) { - // Since we are creating the starting state, we don't have a state to animate from, so - // 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); + mTaskbarLauncherStateController.updateStateForFlag(FLAG_RESUMED, isResumed); + mTaskbarLauncherStateController.applyState( + fromInit ? 0 : QuickstepTransitionManager.CONTENT_ALPHA_DURATION); } /** @@ -268,77 +152,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { */ public Animator createAnimToLauncher(@NonNull LauncherState toState, @NonNull RecentsAnimationCallbacks callbacks, long duration) { - AnimatorSet animatorSet = new AnimatorSet(); - 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); + return mTaskbarLauncherStateController.createAnimToLauncher(toState, callbacks, duration); } /** @@ -358,20 +172,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController { 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 protected void onStashedInAppChanged() { onStashedInAppChanged(mLauncher.getDeviceProfile()); @@ -451,35 +251,4 @@ public class LauncherTaskbarUIController extends TaskbarUIController { mLauncher.logAppLaunch(mControllers.taskbarActivityContext.getStatsLogManager(), item, 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(); - } - } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java new file mode 100644 index 0000000000..2693bc343d --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2021 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.taskbar; + +import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; +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 android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; + +import androidx.annotation.NonNull; + +import com.android.launcher3.BaseQuickstepLauncher; +import com.android.launcher3.LauncherState; +import com.android.launcher3.statemanager.StateManager; +import com.android.launcher3.util.MultiValueAlpha; +import com.android.quickstep.AnimatedFloat; +import com.android.quickstep.RecentsAnimationCallbacks; +import com.android.quickstep.RecentsAnimationController; +import com.android.quickstep.views.RecentsView; +import com.android.systemui.shared.recents.model.ThumbnailData; + +import java.util.HashMap; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * Track LauncherState, RecentsAnimation, resumed state for task bar in one place here and animate + * the task bar accordingly. + */ + public class TaskbarLauncherStateController { + + public static final int FLAG_RESUMED = 1 << 0; + public static final int FLAG_RECENTS_ANIMATION_RUNNING = 1 << 1; + public static final int FLAG_TRANSITION_STATE_START_STASHED = 1 << 2; + public static final int FLAG_TRANSITION_STATE_COMMITTED_STASHED = 1 << 3; + + 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 TaskbarControllers mControllers; + private AnimatedFloat mTaskbarBackgroundAlpha; + private MultiValueAlpha.AlphaProperty mIconAlphaForHome; + private BaseQuickstepLauncher mLauncher; + + private int mPrevState; + private int mState; + + private LauncherState mTargetStateOverride = null; + private LauncherState mTargetStateOverrideForStateTransition = null; + + private boolean mIsAnimatingToLauncherViaGesture; + private boolean mIsAnimatingToLauncherViaResume; + + private final StateManager.StateListener<LauncherState> mStateListener = + new StateManager.StateListener<LauncherState>() { + + @Override + public void onStateTransitionStart(LauncherState toState) { + mTargetStateOverrideForStateTransition = toState; + updateStateForFlag(FLAG_TRANSITION_STATE_START_STASHED, + toState.isTaskbarStashed()); + applyState(); + } + + @Override + public void onStateTransitionComplete(LauncherState finalState) { + updateStateForFlag(FLAG_TRANSITION_STATE_COMMITTED_STASHED, + finalState.isTaskbarStashed()); + applyState(); + } + }; + + public void init(TaskbarControllers controllers, BaseQuickstepLauncher launcher) { + mControllers = controllers; + mLauncher = launcher; + + mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController + .getTaskbarBackgroundAlpha(); + MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha(); + mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME); + mIconAlphaForHome.setConsumer( + (Consumer<Float>) alpha -> mLauncher.getHotseat().setIconsAlpha(alpha > 0 ? 0 : 1)); + + mIconAlignmentForResumedState.finishAnimation(); + onIconAlignmentRatioChanged(); + + mLauncher.getStateManager().addStateListener(mStateListener); + } + + public void onDestroy() { + mIconAlignmentForResumedState.finishAnimation(); + mIconAlignmentForGestureState.finishAnimation(); + mIconAlignmentForLauncherState.finishAnimation(); + + mLauncher.getHotseat().setIconsAlpha(1f); + mLauncher.getStateManager().removeStateListener(mStateListener); + } + + public Animator createAnimToLauncher(@NonNull LauncherState toState, + @NonNull RecentsAnimationCallbacks callbacks, long duration) { + // If going to overview, stash the task bar + // If going home, align the icons to hotseat + AnimatorSet animatorSet = new AnimatorSet(); + + TaskbarStashController stashController = mControllers.taskbarStashController; + stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, + toState.isTaskbarStashed()); + stashController.updateStateForFlag(FLAG_IN_APP, false); + + updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, true); + animatorSet.play(stashController.applyStateWithoutStart(duration)); + animatorSet.play(applyState(duration, false)); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animator) { + mTargetStateOverride = null; + animator.removeListener(this); + } + + @Override + public void onAnimationStart(Animator animator) { + mTargetStateOverride = toState; + } + }); + + TaskBarRecentsAnimationListener listener = new TaskBarRecentsAnimationListener(callbacks); + callbacks.addListener(listener); + RecentsView recentsView = mLauncher.getOverviewPanel(); + recentsView.setTaskLaunchListener(() -> { + listener.endGestureStateOverride(true); + callbacks.removeListener(listener); + }); + return animatorSet; + } + + public boolean isAnimatingToLauncher() { + return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture; + } + + /** + * Updates the proper flag to change the state of the task bar. + * + * Note that this only updates the flag. {@link #applyState()} needs to be called separately. + * + * @param flag The flag to update. + * @param enabled Whether to enable the flag + */ + public void updateStateForFlag(int flag, boolean enabled) { + if (enabled) { + mState |= flag; + } else { + mState &= ~flag; + } + } + + private boolean hasAnyFlag(int flagMask) { + return hasAnyFlag(mState, flagMask); + } + + private boolean hasAnyFlag(int flags, int flagMask) { + return (flags & flagMask) != 0; + } + + public void applyState() { + applyState(TASKBAR_STASH_DURATION); + } + + public void applyState(long duration) { + applyState(duration, true); + } + + public Animator applyState(boolean start) { + return applyState(TASKBAR_STASH_DURATION, start); + } + + public Animator applyState(long duration, boolean start) { + Animator animator = null; + if (mPrevState != mState) { + int changedFlags = mPrevState ^ mState; + animator = onStateChangeApplied(changedFlags, duration, start); + mPrevState = mState; + } + return animator; + } + + private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) { + AnimatorSet animatorSet = new AnimatorSet(); + if (hasAnyFlag(changedFlags, FLAG_RESUMED)) { + boolean isResumed = isResumed(); + ObjectAnimator anim = mIconAlignmentForResumedState + .animateToValue(getCurrentIconAlignmentRatio(), isResumed ? 1 : 0) + .setDuration(duration); + + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIsAnimatingToLauncherViaResume = false; + } + + @Override + public void onAnimationStart(Animator animation) { + mIsAnimatingToLauncherViaResume = isResumed; + + TaskbarStashController stashController = mControllers.taskbarStashController; + stashController.updateStateForFlag(FLAG_IN_APP, !isResumed); + stashController.applyState(duration); + } + }); + animatorSet.play(anim); + } + + if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)) { + boolean isRecentsAnimationRunning = isRecentsAnimationRunning(); + Animator animator = mIconAlignmentForGestureState + .animateToValue(isRecentsAnimationRunning ? 1 : 0); + if (isRecentsAnimationRunning) { + animator.setDuration(duration); + } + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIsAnimatingToLauncherViaGesture = false; + } + + @Override + public void onAnimationStart(Animator animation) { + mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning(); + } + }); + animatorSet.play(animator); + } + + if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_START_STASHED)) { + playStateTransitionAnim(isTransitionStateStartStashed(), animatorSet, duration, + false /* committed */); + } + + if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_COMMITTED_STASHED)) { + playStateTransitionAnim(isTransitionStateCommittedStashed(), animatorSet, duration, + true /* committed */); + } + + if (start) { + animatorSet.start(); + } + return animatorSet; + } + + private void playStateTransitionAnim(boolean isTransitionStateStashed, + AnimatorSet animatorSet, long duration, boolean committed) { + TaskbarStashController controller = mControllers.taskbarStashController; + controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, + isTransitionStateStashed); + Animator stashAnimator = controller.applyStateWithoutStart(duration); + if (stashAnimator != null) { + stashAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (isTransitionStateStashed && committed) { + // Reset hotseat alpha to default + mLauncher.getHotseat().setIconsAlpha(1); + } + mTargetStateOverrideForStateTransition = null; + } + + @Override + public void onAnimationStart(Animator animation) { + mIconAlphaForHome.setValue(mLauncher.getHotseat().getIconsAlpha()); + } + }); + animatorSet.play(stashAnimator); + animatorSet.play(mIconAlignmentForLauncherState.animateToValue( + getCurrentIconAlignmentRatioForLauncherState(), + isTransitionStateStashed ? 0 : 1)); + } else { + mTargetStateOverrideForStateTransition = null; + } + } + + private boolean isResumed() { + return (mState & FLAG_RESUMED) != 0; + } + + private boolean isRecentsAnimationRunning() { + return (mState & FLAG_RECENTS_ANIMATION_RUNNING) != 0; + } + + private boolean isTransitionStateStartStashed() { + return (mState & FLAG_TRANSITION_STATE_START_STASHED) != 0; + } + + private boolean isTransitionStateCommittedStashed() { + return (mState & FLAG_TRANSITION_STATE_COMMITTED_STASHED) != 0; + } + + 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); + } + + private float getCurrentIconAlignmentRatio() { + return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value); + } + + private float getCurrentIconAlignmentRatioForLauncherState() { + return mIconAlignmentForLauncherState.value; + } + + 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); + } + + private final class TaskBarRecentsAnimationListener implements + RecentsAnimationCallbacks.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); + updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, false); + applyState(); + + TaskbarStashController controller = mControllers.taskbarStashController; + controller.updateStateForFlag(FLAG_IN_APP, finishedToApp); + controller.applyState(); + } + } +} |