• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.quickstep.util;
17 
18 import static com.android.launcher3.LauncherState.NORMAL;
19 import static com.android.launcher3.LauncherState.OVERVIEW;
20 
21 import android.animation.Animator;
22 import android.animation.AnimatorSet;
23 import android.util.Log;
24 
25 import androidx.annotation.Nullable;
26 
27 import com.android.launcher3.Launcher;
28 import com.android.launcher3.LauncherState;
29 import com.android.launcher3.anim.AnimationSuccessListener;
30 import com.android.launcher3.statemanager.StateManager;
31 import com.android.launcher3.states.StateAnimationConfig;
32 
33 import java.util.function.BiConsumer;
34 
35 /**
36  * Runs an animation from overview to home. Currently, this animation is just a wrapper around the
37  * normal state transition and may play a {@link WorkspaceRevealAnim} if we're starting from an
38  * upward fling.
39  */
40 public class OverviewToHomeAnim {
41 
42     private static final String TAG = "OverviewToHomeAnim";
43 
44     private final Launcher mLauncher;
45     private final Runnable mOnReachedHome;
46     @Nullable
47     private final BiConsumer<AnimatorSet, Long> mSplitCancelConsumer;
48 
49     // Only run mOnReachedHome when both of these are true.
50     private boolean mIsHomeStaggeredAnimFinished;
51     private boolean mIsOverviewHidden;
52 
OverviewToHomeAnim(Launcher launcher, Runnable onReachedHome, @Nullable BiConsumer<AnimatorSet, Long> splitCancelConsumer)53     public OverviewToHomeAnim(Launcher launcher, Runnable onReachedHome,
54             @Nullable BiConsumer<AnimatorSet, Long> splitCancelConsumer) {
55         mLauncher = launcher;
56         mOnReachedHome = onReachedHome;
57         mSplitCancelConsumer = splitCancelConsumer;
58     }
59 
60     /**
61      * Starts the animation. If velocity < 0 (i.e. upwards), also plays a
62      * {@link WorkspaceRevealAnim}.
63      */
animateWithVelocity(float velocity)64     public void animateWithVelocity(float velocity) {
65         StateManager<LauncherState, Launcher> stateManager = mLauncher.getStateManager();
66         LauncherState startState = stateManager.getState();
67         if (startState != OVERVIEW) {
68             Log.e(TAG, "animateFromOverviewToHome: unexpected start state " + startState);
69         }
70         AnimatorSet anim = new AnimatorSet();
71 
72         boolean playWorkspaceRevealAnim = velocity < 0;
73         if (playWorkspaceRevealAnim) {
74             WorkspaceRevealAnim workspaceRevealAnim = new WorkspaceRevealAnim(mLauncher,
75                     false /* animateOverviewScrim */);
76             workspaceRevealAnim.addAnimatorListener(new AnimationSuccessListener() {
77                 @Override
78                 public void onAnimationSuccess(Animator animator) {
79                     mIsHomeStaggeredAnimFinished = true;
80                     maybeOverviewToHomeAnimComplete();
81                 }
82             });
83             anim.play(workspaceRevealAnim.getAnimators());
84         } else {
85             mIsHomeStaggeredAnimFinished = true;
86         }
87 
88         StateAnimationConfig config = new StateAnimationConfig();
89         if (playWorkspaceRevealAnim) {
90             // WorkspaceRevealAnim handles the depth, so don't interfere.
91             config.animFlags |= StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
92         }
93         config.duration = startState.getTransitionDuration(mLauncher, false /* isToState */);
94         AnimatorSet stateAnim = stateManager.createAtomicAnimation(
95                 startState, NORMAL, config);
96         stateAnim.addListener(new AnimationSuccessListener() {
97             @Override
98             public void onAnimationSuccess(Animator animator) {
99                 mIsOverviewHidden = true;
100                 maybeOverviewToHomeAnimComplete();
101             }
102         });
103 
104         if (mSplitCancelConsumer != null) {
105             // Clear split state when swiping to home
106             mSplitCancelConsumer.accept(anim, config.duration);
107         }
108         anim.play(stateAnim);
109         stateManager.setCurrentAnimation(anim, NORMAL);
110         anim.start();
111     }
112 
113     private void maybeOverviewToHomeAnimComplete() {
114         if (mIsHomeStaggeredAnimFinished && mIsOverviewHidden) {
115             mOnReachedHome.run();
116         }
117     }
118 }
119