Merge "Annotate RecentsView with @Nullable" into sc-v2-dev
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index aa31261..1c0c773 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.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 @@
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 @@
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 @@
@Override
protected boolean isTaskbarTouchable() {
- return !isAnimatingToLauncher();
- }
-
- private boolean isAnimatingToLauncher() {
- return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
+ return !mTaskbarLauncherStateController.isAnimatingToLauncher();
}
@Override
@@ -240,24 +139,9 @@
}
}
- 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 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 @@
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 @@
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 0000000..2693bc3
--- /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();
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java
index bd39391..326141d 100644
--- a/src/com/android/launcher3/util/MultiValueAlpha.java
+++ b/src/com/android/launcher3/util/MultiValueAlpha.java
@@ -24,6 +24,7 @@
import com.android.launcher3.anim.AlphaUpdateListener;
import java.util.Arrays;
+import java.util.function.Consumer;
/**
* Utility class to handle separating a single value as a factor of multiple values
@@ -85,6 +86,8 @@
// Factor of all other alpha channels, only valid if mMyMask is present in mValidMask.
private float mOthers = 1;
+ private Consumer<Float> mConsumer;
+
AlphaProperty(int myMask) {
mMyMask = myMask;
}
@@ -109,16 +112,24 @@
mValidMask = mMyMask;
mValue = value;
- mView.setAlpha(mOthers * mValue);
+ final float alpha = mOthers * mValue;
+ mView.setAlpha(alpha);
if (mUpdateVisibility) {
AlphaUpdateListener.updateVisibility(mView);
}
+ if (mConsumer != null) {
+ mConsumer.accept(mValue);
+ }
}
public float getValue() {
return mValue;
}
+ public void setConsumer(Consumer<Float> consumer) {
+ mConsumer = consumer;
+ }
+
@Override
public String toString() {
return Float.toString(mValue);
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 194ee4f..36af8f0 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -28,6 +28,7 @@
import com.android.launcher3.tapl.WidgetResizeFrame;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -47,6 +48,7 @@
@Test
@PortraitLandscape
+ @ScreenRecord // b/204807156
public void testDragIcon() throws Throwable {
clearHomescreen();
mDevice.pressHome();
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index fa39ce0..758c426 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -45,6 +45,7 @@
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
@@ -138,6 +139,7 @@
}
@Test
+ @ScreenRecord // b/204807156
public void testPendingWidget_autoRestored() {
// A non-restored widget with no config screen gets restored automatically.
LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false);