1b745afbdd75157c73d581b345118cdaff99e912dWinson Chung/*
2b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * Copyright (C) 2015 The Android Open Source Project
3b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *
4b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * Licensed under the Apache License, Version 2.0 (the "License");
5b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * you may not use this file except in compliance with the License.
6b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * You may obtain a copy of the License at
7b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *
8b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *      http://www.apache.org/licenses/LICENSE-2.0
9b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *
10b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * Unless required by applicable law or agreed to in writing, software
11b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * distributed under the License is distributed on an "AS IS" BASIS,
12b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * See the License for the specific language governing permissions and
14b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * limitations under the License.
15b745afbdd75157c73d581b345118cdaff99e912dWinson Chung */
16b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
17b745afbdd75157c73d581b345118cdaff99e912dWinson Chungpackage com.android.launcher3;
18b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
19b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.animation.Animator;
20b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.animation.AnimatorListenerAdapter;
21b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.animation.AnimatorSet;
22b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.animation.ObjectAnimator;
23b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.animation.PropertyValuesHolder;
24b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.animation.TimeInterpolator;
250bb211a9d5cd4eabcbf46385bbfb9895e5cd7325Tony Wickhamimport android.animation.ValueAnimator;
26b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.content.res.Resources;
27b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.util.Log;
28b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.view.View;
29b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.view.animation.AccelerateInterpolator;
301558893b873cd55b2df779f594f1de3c370d3328Adam Cohen
315f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungimport com.android.launcher3.allapps.AllAppsContainerView;
32645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.allapps.AllAppsTransitionController;
33b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyalimport com.android.launcher3.anim.AnimationLayerSet;
34af479026526be438dd6e4c32dba4c5cabe4f46fbJon Mirandaimport com.android.launcher3.anim.CircleRevealOutlineProvider;
35c06af333cbcebb183d13d004cccf5c9d69a70af0Mario Bertschlerimport com.android.launcher3.config.FeatureFlags;
36091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.widget.WidgetsContainerView;
381558893b873cd55b2df779f594f1de3c370d3328Adam Cohen
39b745afbdd75157c73d581b345118cdaff99e912dWinson Chung/**
40b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * TODO: figure out what kind of tests we can write for this
41b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *
42b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * Things to test when changing the following class.
43b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Home from workspace
44b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from center screen
45b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from other screens
46b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Home from all apps
47b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from center screen
48b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from other screens
49b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Back from all apps
50b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from center screen
51b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from other screens
52b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Launch app from workspace and quit
53b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
54b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with home
55b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Launch app from all apps and quit
56b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
57b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with home
58b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Go to a screen that's not the default, then all
59b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *     apps, and launch and app, and go back
60b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
61b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          -with home
62b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - On workspace, long press power and go back
63b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
64b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with home
65b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - On all apps, long press power and go back
66b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
67b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with home
68b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - On workspace, power off
69b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - On all apps, power off
70b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Launch an app and turn off the screen while in that app
71b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - Go back with home key
72b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - Go back with back key  TODO: make this not go to workspace
73b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From all apps
74b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From workspace
75b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Enter and exit car mode (becuase it causes an extra configuration changed)
76b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From all apps
77b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From the center workspace
78b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From another workspace
79b745afbdd75157c73d581b345118cdaff99e912dWinson Chung */
80b745afbdd75157c73d581b345118cdaff99e912dWinson Chungpublic class LauncherStateTransitionAnimation {
81b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
82645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    /**
83d725f644b70239332a4440173e6411e9ffb169a0Hyunyoung Song     * animation used for the widget tray
84645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     */
85645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public static final int CIRCULAR_REVEAL = 0;
86645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    /**
87d725f644b70239332a4440173e6411e9ffb169a0Hyunyoung Song     * animation used for all apps tray
88645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     */
89645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public static final int PULLUP = 1;
90645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
910ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    private static final float FINAL_REVEAL_ALPHA_FOR_WIDGETS = 0.3f;
920ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
93b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
94b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Private callbacks made during transition setup.
95b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
960ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    private static class PrivateTransitionCallbacks {
970ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        private final float materialRevealViewFinalAlpha;
980ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
990ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks(float revealAlpha) {
1000ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            materialRevealViewFinalAlpha = revealAlpha;
101b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
1020ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
103b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        float getMaterialRevealViewStartFinalRadius() {
104b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            return 0;
105b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
106b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(View revealView,
10798ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                View buttonView) {
108b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            return null;
109b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
11076648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung        void onTransitionComplete() {}
111b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
112b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
1130ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public static final String TAG = "LSTAnimation";
114b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
115b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    public static final int SINGLE_FRAME_DELAY = 16;
116b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
117091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk Launcher mLauncher;
118006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    @Thunk AnimatorSet mCurrentAnimation;
119645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    AllAppsTransitionController mAllAppsController;
120b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
121645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public LauncherStateTransitionAnimation(Launcher l, AllAppsTransitionController allAppsController) {
122b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        mLauncher = l;
123645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mAllAppsController = allAppsController;
124b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
125b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
126b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
127b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Starts an animation to the apps view.
128b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
1295606e070592521c80033381fc0536d4aa1351695Sunny Goyal    public void startAnimationToAllApps(final boolean animated) {
1305f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final AllAppsContainerView toView = mLauncher.getAppsView();
131bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal        final View buttonView = mLauncher.getStartViewForAllAppsRevealAnimation();
1320ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks(1f) {
133b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
134b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public float getMaterialRevealViewStartFinalRadius() {
1352e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
136b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return allAppsButtonSize / 2;
137b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
138b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
139b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
140b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    final View revealView, final View allAppsButtonView) {
141b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
142b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationStart(Animator animation) {
143b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.INVISIBLE);
144b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
145b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
146b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.VISIBLE);
147b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
148b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
149b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
15076648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            @Override
15176648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            void onTransitionComplete() {
152aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
15376648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            }
154b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
155ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Only animate the search bar if animating from spring loaded mode back to all apps
156db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        startAnimationToOverlay(
157d725f644b70239332a4440173e6411e9ffb169a0Hyunyoung Song                Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, PULLUP, cb);
158b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
159b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
160b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
161b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Starts an animation to the widgets view.
162b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
163db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    public void startAnimationToWidgets(final boolean animated) {
1643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        final WidgetsContainerView toView = mLauncher.getWidgetsView();
16598ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        final View buttonView = mLauncher.getWidgetsButton();
166db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        startAnimationToOverlay(
167645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, animated, CIRCULAR_REVEAL,
1688fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS){
1698fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    @Override
1708fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    void onTransitionComplete() {
171aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                        mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
1728fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    }
1738fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                });
174b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
175b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
176b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
1776d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the current overlay view.
178b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
179b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    public void startAnimationToWorkspace(final Launcher.State fromState,
180006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
1812a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final boolean animated, final Runnable onCompleteRunnable) {
182b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        if (toWorkspaceState != Workspace.State.NORMAL &&
183b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                toWorkspaceState != Workspace.State.SPRING_LOADED &&
184b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                toWorkspaceState != Workspace.State.OVERVIEW) {
185b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            Log.e(TAG, "Unexpected call to startAnimationToWorkspace");
186b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
187b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
1889dcf0a3ef7595f58aedec7773e7bc3b9075fb3caHyunyoung Song        if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED
1899dcf0a3ef7595f58aedec7773e7bc3b9075fb3caHyunyoung Song                || mAllAppsController.isTransitioning()) {
1902a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            startAnimationToWorkspaceFromAllApps(fromWorkspaceState, toWorkspaceState,
191d725f644b70239332a4440173e6411e9ffb169a0Hyunyoung Song                    animated, PULLUP, onCompleteRunnable);
1926d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else if (fromState == Launcher.State.WIDGETS ||
1936d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                fromState == Launcher.State.WIDGETS_SPRING_LOADED) {
1942a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            startAnimationToWorkspaceFromWidgets(fromWorkspaceState, toWorkspaceState,
195dc61c4d41468a8beced2863de1b863b340cf49baWinson Chung                    animated, onCompleteRunnable);
1966d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else {
1976d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            startAnimationToNewWorkspaceState(fromWorkspaceState, toWorkspaceState,
1986d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    animated, onCompleteRunnable);
199b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
200b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
201b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
202b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
203b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Creates and starts a new animation to a particular overlay view.
204b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
205191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song    private void startAnimationToOverlay(
206db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            final Workspace.State toWorkspaceState,
2070ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View buttonView, final BaseContainerView toView,
208645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final boolean animated, int animType, final PrivateTransitionCallbacks pCb) {
209006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
210b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final Resources res = mLauncher.getResources();
2115f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
212e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song        final int revealDurationSlide = res.getInteger(R.integer.config_overlaySlideRevealTime);
213e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song
2140ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        final int itemsAlphaStagger = res.getInteger(R.integer.config_overlayItemsAlphaStagger);
215b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
216b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
217b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
218b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // If for some reason our views aren't initialized, don't animate
21998ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        boolean initialized = buttonView != null;
220b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
221b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // Cancel the current animation
222b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        cancelAnimation();
223b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
2240ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        final View contentView = toView.getContentView();
225db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState,
22661d9e78f23efcf43be1945d4233780ac89db99d9Winson                animated, initialized, animation, layerViews);
227645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (!animated || !initialized) {
228d725f644b70239332a4440173e6411e9ffb169a0Hyunyoung Song            if (toWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
229ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song                mAllAppsController.finishPullUp();
230ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song            }
231645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setTranslationX(0.0f);
232645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setTranslationY(0.0f);
233645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setScaleX(1.0f);
234645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setScaleY(1.0f);
235645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setAlpha(1.0f);
236645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setVisibility(View.VISIBLE);
237645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
238645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            // Show the content view
239645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            contentView.setVisibility(View.VISIBLE);
240645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            pCb.onTransitionComplete();
241191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            return;
242645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
243645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (animType == CIRCULAR_REVEAL) {
244b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Setup the reveal view animation
2450ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View revealView = toView.getRevealView();
2460ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
247b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            int width = revealView.getMeasuredWidth();
248b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            int height = revealView.getMeasuredHeight();
249f7a29e83f06909b378dba39c83a522375682710aSunny Goyal            float revealRadius = (float) Math.hypot(width / 2, height / 2);
250b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setVisibility(View.VISIBLE);
251b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setAlpha(0f);
252b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setTranslationY(0f);
253b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setTranslationX(0f);
254b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
255b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Calculate the final animation values
256a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            int[] buttonViewToPanelDelta =
257a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    Utilities.getCenterDeltaInScreenSpace(revealView, buttonView);
258a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            final float revealViewToAlpha = pCb.materialRevealViewFinalAlpha;
259a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            final float revealViewToXDrift = buttonViewToPanelDelta[0];
260a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            final float revealViewToYDrift = buttonViewToPanelDelta[1];
261b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
262b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Create the animators
263b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelAlpha =
2645d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.ALPHA, revealViewToAlpha, 1f);
265b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelDriftY =
2665d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, revealViewToYDrift, 0);
267b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelDriftX =
2685d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.TRANSLATION_X, revealViewToXDrift, 0);
269b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator panelAlphaAndDrift = ObjectAnimator.ofPropertyValuesHolder(revealView,
270b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    panelAlpha, panelDriftY, panelDriftX);
271b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            panelAlphaAndDrift.setDuration(revealDuration);
272b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
273b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
274b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Play the animation
275b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(revealView);
276006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(panelAlphaAndDrift);
277b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
278b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Setup the animation for the content view
279b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setVisibility(View.VISIBLE);
280b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setAlpha(0f);
281b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setTranslationY(revealViewToYDrift);
282b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(contentView);
283b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
284b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Create the individual animators
285b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator pageDrift = ObjectAnimator.ofFloat(contentView, "translationY",
286b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    revealViewToYDrift, 0);
287b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setDuration(revealDuration);
288b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
289b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setStartDelay(itemsAlphaStagger);
290006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(pageDrift);
291b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
292b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 0f, 1f);
293b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setDuration(revealDuration);
294b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
295b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setStartDelay(itemsAlphaStagger);
296006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(itemsAlpha);
297b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
298a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            float startRadius = pCb.getMaterialRevealViewStartFinalRadius();
299a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            AnimatorListenerAdapter listener = pCb.getMaterialRevealViewAnimatorListener(
300a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    revealView, buttonView);
301a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            Animator reveal = new CircleRevealOutlineProvider(width / 2, height / 2,
302a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    startRadius, revealRadius).createRevealAnimator(revealView);
303a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            reveal.setDuration(revealDuration);
304a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
305a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            if (listener != null) {
306a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                reveal.addListener(listener);
307b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
308a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            animation.play(reveal);
309b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
310006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.addListener(new AnimatorListenerAdapter() {
311b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                @Override
312b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                public void onAnimationEnd(Animator animation) {
313b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Hide the reveal view
314b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    revealView.setVisibility(View.INVISIBLE);
315b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
316b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // This can hold unnecessary references to views.
317006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    cleanupAnimation();
31876648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                    pCb.onTransitionComplete();
319b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
320b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
321b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            });
322b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
323b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            toView.bringToFront();
324b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            toView.setVisibility(View.VISIBLE);
325b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal
326b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            animation.addListener(layerViews);
327db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            toView.post(new StartAnimRunnable(animation, toView));
328191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
329645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        } else if (animType == PULLUP) {
3307f522a25c39ceb35aa009f029abe74497f03c403Jon Miranda            if (!FeatureFlags.LAUNCHER3_PHYSICS) {
3317f522a25c39ceb35aa009f029abe74497f03c403Jon Miranda                // We are animating the content view alpha, so ensure we have a layer for it.
3327f522a25c39ceb35aa009f029abe74497f03c403Jon Miranda                layerViews.addView(contentView);
3337f522a25c39ceb35aa009f029abe74497f03c403Jon Miranda            }
33461d9e78f23efcf43be1945d4233780ac89db99d9Winson
335645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            animation.addListener(new AnimatorListenerAdapter() {
336191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                @Override
337191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                public void onAnimationEnd(Animator animation) {
338191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                    cleanupAnimation();
339191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                    pCb.onTransitionComplete();
340191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                }
341645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            });
342191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            boolean shouldPost = mAllAppsController.animateToAllApps(animation, revealDurationSlide);
343b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
344db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Runnable startAnimRunnable = new StartAnimRunnable(animation, toView);
345191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
346b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
347191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            if (shouldPost) {
348191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                toView.post(startAnimRunnable);
349191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            } else {
350191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                startAnimRunnable.run();
351191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            }
352b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
353b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
354b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
355b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
356685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham     * Plays animations used by various transitions.
357685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham     */
3587c50b31f57e3e3ec1f433d243afe05554dcaf977Sunny Goyal    private void playCommonTransitionAnimations(
359db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Workspace.State toWorkspaceState,
36061d9e78f23efcf43be1945d4233780ac89db99d9Winson            boolean animated, boolean initialized, AnimatorSet animation,
361b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            AnimationLayerSet layerViews) {
362685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        // Create the workspace animation.
363685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        // NOTE: this call apparently also sets the state for the workspace if !animated
364685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState,
365685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham                animated, layerViews);
366685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham
367685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        if (animated && initialized) {
368685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            // Play the workspace animation
369685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            if (workspaceAnim != null) {
370685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham                animation.play(workspaceAnim);
371685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            }
372685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        }
373685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham    }
374685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham
375685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham    /**
3766d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the apps view.
377b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
378006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    private void startAnimationToWorkspaceFromAllApps(final Workspace.State fromWorkspaceState,
379645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final Workspace.State toWorkspaceState, final boolean animated, int type,
3802a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final Runnable onCompleteRunnable) {
3810ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        // No alpha anim from all apps
3820ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks(1f) {
383b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
384b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            float getMaterialRevealViewStartFinalRadius() {
3852e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
386b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return allAppsButtonSize / 2;
387b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
388b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
389b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
390b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    final View revealView, final View allAppsButtonView) {
391b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
392b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationStart(Animator animation) {
393b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // We set the alpha instead of visibility to ensure that the focus does not
394b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // get taken from the all apps view
395b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.VISIBLE);
396b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setAlpha(0f);
397b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
398b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
399b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Hide the reveal view
400b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        revealView.setVisibility(View.INVISIBLE);
401b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
402b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Show the all apps button, and focus it
403b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setAlpha(1f);
404b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
405b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
406b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
4078fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            @Override
4088fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            void onTransitionComplete() {
409aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
4108fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            }
411b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
412ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Only animate the search bar if animating to spring loaded mode from all apps
413191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        startAnimationToWorkspaceFromOverlay(fromWorkspaceState, toWorkspaceState,
41414709c6eea128a900345f1109468d7a5b0ed900eJon Miranda                mLauncher.getStartViewForAllAppsRevealAnimation(), mLauncher.getAppsView(),
415645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                animated, type, onCompleteRunnable, cb);
416b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
417b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
418b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
4196d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the widgets view.
420b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
421006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    private void startAnimationToWorkspaceFromWidgets(final Workspace.State fromWorkspaceState,
4226d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Workspace.State toWorkspaceState, final boolean animated,
4232a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final Runnable onCompleteRunnable) {
4244cea4c830283e017fc36197cfe9d7ce713aec49dHyunyoung Song        final WidgetsContainerView widgetsView = mLauncher.getWidgetsView();
4250ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb =
4260ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS) {
427b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
428b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
42998ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                    final View revealView, final View widgetsButtonView) {
430b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
431b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
432b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Hide the reveal view
433b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        revealView.setVisibility(View.INVISIBLE);
434b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
435b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
436b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
4378fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            @Override
4388fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            void onTransitionComplete() {
439aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
4408fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            }
441b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
442191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        startAnimationToWorkspaceFromOverlay(
4430ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                fromWorkspaceState, toWorkspaceState,
4447c50b31f57e3e3ec1f433d243afe05554dcaf977Sunny Goyal                mLauncher.getWidgetsButton(), widgetsView,
445645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                animated, CIRCULAR_REVEAL, onCompleteRunnable, cb);
446b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
447b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
448b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
4496d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from another workspace state, e.g. normal to overview.
4506d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     */
4516d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    private void startAnimationToNewWorkspaceState(final Workspace.State fromWorkspaceState,
4526d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Workspace.State toWorkspaceState, final boolean animated,
4536d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Runnable onCompleteRunnable) {
4546d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        final View fromWorkspace = mLauncher.getWorkspace();
455b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
4566d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
4576d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
4586d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        // Cancel the current animation
4596d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        cancelAnimation();
4606d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
461db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState, animated, animated, animation, layerViews);
462f3e35d93318190f995e6a0fc9d0441ac844b67e4Jon Miranda        mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
463f3e35d93318190f995e6a0fc9d0441ac844b67e4Jon Miranda
4646d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        if (animated) {
4656d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            animation.addListener(new AnimatorListenerAdapter() {
4666d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                @Override
4676d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                public void onAnimationEnd(Animator animation) {
4686d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    // Run any queued runnables
4696d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    if (onCompleteRunnable != null) {
4706d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                        onCompleteRunnable.run();
4716d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    }
4726d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
4736d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    // This can hold unnecessary references to views.
4746d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    cleanupAnimation();
4756d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                }
4766d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            });
477db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            animation.addListener(layerViews);
478db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            fromWorkspace.post(new StartAnimRunnable(animation, null));
4796d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            mCurrentAnimation = animation;
4806d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else /* if (!animated) */ {
4816d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            // Run any queued runnables
4826d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            if (onCompleteRunnable != null) {
4836d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                onCompleteRunnable.run();
4846d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            }
4856d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
4866d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            mCurrentAnimation = null;
4876d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        }
4886d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    }
4896d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
4906d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    /**
491b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Creates and starts a new animation to the workspace.
492b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
493191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song    private void startAnimationToWorkspaceFromOverlay(
4940ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
4950ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View buttonView, final BaseContainerView fromView,
496645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final boolean animated, int animType, final Runnable onCompleteRunnable,
497006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            final PrivateTransitionCallbacks pCb) {
498006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
499b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final Resources res = mLauncher.getResources();
5005f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
501e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song        final int revealDurationSlide = res.getInteger(R.integer.config_overlaySlideRevealTime);
502a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal        final int itemsAlphaStagger = res.getInteger(R.integer.config_overlayItemsAlphaStagger);
503b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
504b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final View toView = mLauncher.getWorkspace();
50561d9e78f23efcf43be1945d4233780ac89db99d9Winson        final View revealView = fromView.getRevealView();
50661d9e78f23efcf43be1945d4233780ac89db99d9Winson        final View contentView = fromView.getContentView();
507b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
508b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
509b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
510b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // If for some reason our views aren't initialized, don't animate
51198ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        boolean initialized = buttonView != null;
512b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
513b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // Cancel the current animation
514b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        cancelAnimation();
515b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
516db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState,
51761d9e78f23efcf43be1945d4233780ac89db99d9Winson                animated, initialized, animation, layerViews);
51874b5af35291f620d2f09f313f2e9bd9f817b9d27Hyunyoung Song        if (!animated || !initialized) {
519d725f644b70239332a4440173e6411e9ffb169a0Hyunyoung Song            if (fromWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
5207ccc4625e38b8107cd1882272aec36967874a5ccHyunyoung Song                mAllAppsController.finishPullDown();
521b11ae50fcb2bb07ee77645fdacdf90f67f58dae4Hyunyoung Song            }
522645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            fromView.setVisibility(View.GONE);
523645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            pCb.onTransitionComplete();
5240bb211a9d5cd4eabcbf46385bbfb9895e5cd7325Tony Wickham
525645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            // Run any queued runnables
526645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            if (onCompleteRunnable != null) {
527645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                onCompleteRunnable.run();
528645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            }
529191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            return;
530645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
531645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (animType == CIRCULAR_REVEAL) {
532b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // hideAppsCustomizeHelper is called in some cases when it is already hidden
533b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // don't perform all these no-op animations. In particularly, this was causing
534b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // the all-apps button to pop in and out.
535b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            if (fromView.getVisibility() == View.VISIBLE) {
536b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                int width = revealView.getMeasuredWidth();
537b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                int height = revealView.getMeasuredHeight();
538f7a29e83f06909b378dba39c83a522375682710aSunny Goyal                float revealRadius = (float) Math.hypot(width / 2, height / 2);
539b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setVisibility(View.VISIBLE);
540b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setAlpha(1f);
541b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setTranslationY(0);
542b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal                layerViews.addView(revealView);
543b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
544b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Calculate the final animation values
545a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView, buttonView);
546a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                final float revealViewToXDrift = buttonViewToPanelDelta[0];
547a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                final float revealViewToYDrift = buttonViewToPanelDelta[1];
548b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
549b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // The vertical motion of the apps panel should be delayed by one frame
550b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // from the conceal animation in order to give the right feel. We correspondingly
551b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // shorten the duration so that the slide and conceal end at the same time.
552a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                TimeInterpolator decelerateInterpolator = new LogDecelerateInterpolator(100, 0);
5531558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator panelDriftY = ObjectAnimator.ofFloat(revealView, "translationY",
554b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToYDrift);
555b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
556b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
557b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setInterpolator(decelerateInterpolator);
558006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(panelDriftY);
559b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
5601558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator panelDriftX = ObjectAnimator.ofFloat(revealView, "translationX",
561b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToXDrift);
562b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
563b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
564b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setInterpolator(decelerateInterpolator);
565006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(panelDriftX);
566b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
567b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Setup animation for the reveal panel alpha
568a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                if (pCb.materialRevealViewFinalAlpha != 1f) {
5691558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                    ObjectAnimator panelAlpha = ObjectAnimator.ofFloat(revealView, "alpha",
570a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                            1f, pCb.materialRevealViewFinalAlpha);
571a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    panelAlpha.setDuration(revealDuration);
572b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    panelAlpha.setInterpolator(decelerateInterpolator);
573006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    animation.play(panelAlpha);
574b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
575b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
576b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Setup the animation for the content view
577b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal                layerViews.addView(contentView);
578b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
579b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Create the individual animators
5801558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator pageDrift = ObjectAnimator.ofFloat(contentView, "translationY",
581b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToYDrift);
582b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                contentView.setTranslationY(0);
583b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
584b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setInterpolator(decelerateInterpolator);
585b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
586006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(pageDrift);
587b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
588b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                contentView.setAlpha(1f);
5891558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 1f, 0f);
590b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                itemsAlpha.setDuration(100);
591b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                itemsAlpha.setInterpolator(decelerateInterpolator);
592006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(itemsAlpha);
593b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
5943f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                // Invalidate the scrim throughout the animation to ensure the highlight
5953f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                // cutout is correct throughout.
5963f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                ValueAnimator invalidateScrim = ValueAnimator.ofFloat(0f, 1f);
5973f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                invalidateScrim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
5983f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    @Override
5993f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    public void onAnimationUpdate(ValueAnimator animation) {
6003f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                        mLauncher.getDragLayer().invalidateScrim();
6013f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    }
6023f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                });
6033f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                animation.play(invalidateScrim);
6043f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham
605a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                // Animate the all apps button
606a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                float finalRadius = pCb.getMaterialRevealViewStartFinalRadius();
607a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                AnimatorListenerAdapter listener =
608a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                        pCb.getMaterialRevealViewAnimatorListener(revealView, buttonView);
609a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                Animator reveal = new CircleRevealOutlineProvider(width / 2, height / 2,
610a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                        revealRadius, finalRadius).createRevealAnimator(revealView);
611a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
612a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                reveal.setDuration(revealDuration);
613a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                reveal.setStartDelay(itemsAlphaStagger);
614a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                if (listener != null) {
615a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    reveal.addListener(listener);
616b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
617a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                animation.play(reveal);
618b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
619b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
620006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.addListener(new AnimatorListenerAdapter() {
621b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                @Override
622b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                public void onAnimationEnd(Animator animation) {
623b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    fromView.setVisibility(View.GONE);
624b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Run any queued runnables
625b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    if (onCompleteRunnable != null) {
626b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        onCompleteRunnable.run();
627b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
628b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
629b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Reset page transforms
630b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    if (contentView != null) {
631b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setTranslationX(0);
632b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setTranslationY(0);
633b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setAlpha(1);
634b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
635b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
636b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // This can hold unnecessary references to views.
637006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    cleanupAnimation();
63876648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                    pCb.onTransitionComplete();
639b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
640b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            });
641b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
642191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
643b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
644db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            fromView.post(new StartAnimRunnable(animation, null));
645645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        } else if (animType == PULLUP) {
64661d9e78f23efcf43be1945d4233780ac89db99d9Winson            // We are animating the content view alpha, so ensure we have a layer for it
647b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(contentView);
64861d9e78f23efcf43be1945d4233780ac89db99d9Winson
649645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            animation.addListener(new AnimatorListenerAdapter() {
650eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                boolean canceled = false;
651645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                @Override
652eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                public void onAnimationCancel(Animator animation) {
653eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                    canceled = true;
654645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                }
655b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
656645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                @Override
657645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                public void onAnimationEnd(Animator animation) {
658eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                    if (canceled) return;
659645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    // Run any queued runnables
660645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    if (onCompleteRunnable != null) {
661645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                        onCompleteRunnable.run();
662645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    }
66361d9e78f23efcf43be1945d4233780ac89db99d9Winson
664645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    cleanupAnimation();
665645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    pCb.onTransitionComplete();
666645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                }
667eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song
668645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            });
669191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            boolean shouldPost = mAllAppsController.animateToWorkspace(animation, revealDurationSlide);
670eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song
671db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Runnable startAnimRunnable = new StartAnimRunnable(animation, toView);
672191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
673b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
674191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            if (shouldPost) {
675191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                fromView.post(startAnimRunnable);
676191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            } else {
677191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                startAnimRunnable.run();
678191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            }
679b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
680191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        return;
681b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
682b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
683006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    /**
684b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Cancels the current animation.
685b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
686b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    private void cancelAnimation() {
687006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        if (mCurrentAnimation != null) {
688006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation.setDuration(0);
689006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation.cancel();
690006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation = null;
691b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
692b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
693006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung
694d1ea63f24a751521e6c35cc06be0e548e0b04f23Sunny Goyal    @Thunk void cleanupAnimation() {
695006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        mCurrentAnimation = null;
696006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    }
697db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
698db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    private class StartAnimRunnable implements Runnable {
699db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
700db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        private final AnimatorSet mAnim;
701db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        private final View mViewToFocus;
702db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
703db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        public StartAnimRunnable(AnimatorSet anim, View viewToFocus) {
704db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mAnim = anim;
705db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mViewToFocus = viewToFocus;
706db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        }
707db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
708db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        @Override
709db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        public void run() {
710db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            if (mCurrentAnimation != mAnim) {
711db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal                return;
712db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            }
713db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            if (mViewToFocus != null) {
714db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal                mViewToFocus.requestFocus();
715db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            }
716db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mAnim.start();
717db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        }
718db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    }
7191558893b873cd55b2df779f594f1de3c370d3328Adam Cohen}
720