LauncherStateTransitionAnimation.java revision db364379312e56a3a3905a54d0de783062a92a73
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;
26756cd26592dee6b956becdc24d60995c64de9153Sunny Goyalimport android.annotation.TargetApi;
27b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.content.res.Resources;
28756cd26592dee6b956becdc24d60995c64de9153Sunny Goyalimport android.os.Build;
29b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.util.Log;
30b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.view.View;
31b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.view.animation.AccelerateInterpolator;
32db364379312e56a3a3905a54d0de783062a92a73Sunny Goyalimport android.view.animation.Animation;
33b745afbdd75157c73d581b345118cdaff99e912dWinson Chungimport android.view.animation.DecelerateInterpolator;
341558893b873cd55b2df779f594f1de3c370d3328Adam Cohen
355f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungimport com.android.launcher3.allapps.AllAppsContainerView;
36645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.allapps.AllAppsTransitionController;
37b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyalimport com.android.launcher3.anim.AnimationLayerSet;
38645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.config.FeatureFlags;
398f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickhamimport com.android.launcher3.util.CircleRevealOutlineProvider;
40091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.widget.WidgetsContainerView;
421558893b873cd55b2df779f594f1de3c370d3328Adam Cohen
43b745afbdd75157c73d581b345118cdaff99e912dWinson Chung/**
44b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * TODO: figure out what kind of tests we can write for this
45b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *
46b745afbdd75157c73d581b345118cdaff99e912dWinson Chung * Things to test when changing the following class.
47b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Home from workspace
48b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from center screen
49b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from other screens
50b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Home from all apps
51b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from center screen
52b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from other screens
53b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Back from all apps
54b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from center screen
55b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - from other screens
56b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Launch app from workspace and quit
57b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
58b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with home
59b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Launch app from all apps and quit
60b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
61b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with home
62b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Go to a screen that's not the default, then all
63b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *     apps, and launch and app, and go back
64b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
65b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          -with home
66b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - On workspace, long press power and go back
67b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
68b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with home
69b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - On all apps, long press power and go back
70b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with back
71b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - with home
72b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - On workspace, power off
73b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - On all apps, power off
74b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Launch an app and turn off the screen while in that app
75b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - Go back with home key
76b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - Go back with back key  TODO: make this not go to workspace
77b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From all apps
78b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From workspace
79b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *   - Enter and exit car mode (becuase it causes an extra configuration changed)
80b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From all apps
81b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From the center workspace
82b745afbdd75157c73d581b345118cdaff99e912dWinson Chung *          - From another workspace
83b745afbdd75157c73d581b345118cdaff99e912dWinson Chung */
84b745afbdd75157c73d581b345118cdaff99e912dWinson Chungpublic class LauncherStateTransitionAnimation {
85b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
86645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    /**
87645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     * animation used for all apps and widget tray when
88645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     *{@link FeatureFlags#LAUNCHER3_ALL_APPS_PULL_UP} is {@code false}
89645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     */
90645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public static final int CIRCULAR_REVEAL = 0;
91645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    /**
92645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     * animation used for all apps and not widget tray when
93645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     *{@link FeatureFlags#LAUNCHER3_ALL_APPS_PULL_UP} is {@code true}
94645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     */
95645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public static final int PULLUP = 1;
96645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
970ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    private static final float FINAL_REVEAL_ALPHA_FOR_WIDGETS = 0.3f;
980ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
99b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
100b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Private callbacks made during transition setup.
101b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
1020ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    private static class PrivateTransitionCallbacks {
1030ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        private final float materialRevealViewFinalAlpha;
1040ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
1050ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks(float revealAlpha) {
1060ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            materialRevealViewFinalAlpha = revealAlpha;
107b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
1080ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
109b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        float getMaterialRevealViewStartFinalRadius() {
110b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            return 0;
111b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
112b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(View revealView,
11398ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                View buttonView) {
114b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            return null;
115b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
11676648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung        void onTransitionComplete() {}
117b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
118b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
1190ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public static final String TAG = "LSTAnimation";
120b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
121b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    public static final int SINGLE_FRAME_DELAY = 16;
122b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
123091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk Launcher mLauncher;
124006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    @Thunk AnimatorSet mCurrentAnimation;
125645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    AllAppsTransitionController mAllAppsController;
126b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
127645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public LauncherStateTransitionAnimation(Launcher l, AllAppsTransitionController allAppsController) {
128b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        mLauncher = l;
129645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mAllAppsController = allAppsController;
130b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
131b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
132b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
133b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Starts an animation to the apps view.
13476648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung     *
13576648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung     * @param startSearchAfterTransition Immediately starts app search after the transition to
13676648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung     *                                   All Apps is completed.
137b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
138db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    public void startAnimationToAllApps(
139006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            final boolean animated, final boolean startSearchAfterTransition) {
1405f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final AllAppsContainerView toView = mLauncher.getAppsView();
141bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal        final View buttonView = mLauncher.getStartViewForAllAppsRevealAnimation();
1420ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks(1f) {
143b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
144b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public float getMaterialRevealViewStartFinalRadius() {
1452e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
146b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return allAppsButtonSize / 2;
147b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
148b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
149b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
150b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    final View revealView, final View allAppsButtonView) {
151b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
152b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationStart(Animator animation) {
153b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.INVISIBLE);
154b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
155b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
156b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.VISIBLE);
157b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
158b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
159b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
16076648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            @Override
16176648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            void onTransitionComplete() {
162aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
16376648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                if (startSearchAfterTransition) {
16476648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                    toView.startAppsSearch();
16576648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                }
16676648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            }
167b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
168645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        int animType = CIRCULAR_REVEAL;
169645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
170645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            animType = PULLUP;
171645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
172ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Only animate the search bar if animating from spring loaded mode back to all apps
173db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        startAnimationToOverlay(
174645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, animType, cb);
175b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
176b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
177b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
178b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Starts an animation to the widgets view.
179b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
180db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    public void startAnimationToWidgets(final boolean animated) {
1813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        final WidgetsContainerView toView = mLauncher.getWidgetsView();
18298ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        final View buttonView = mLauncher.getWidgetsButton();
183db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        startAnimationToOverlay(
184645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, animated, CIRCULAR_REVEAL,
1858fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS){
1868fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    @Override
1878fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    void onTransitionComplete() {
188aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                        mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
1898fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    }
1908fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                });
191b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
192b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
193b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
1946d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the current overlay view.
195b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
196b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    public void startAnimationToWorkspace(final Launcher.State fromState,
197006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
1982a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final boolean animated, final Runnable onCompleteRunnable) {
199b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        if (toWorkspaceState != Workspace.State.NORMAL &&
200b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                toWorkspaceState != Workspace.State.SPRING_LOADED &&
201b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                toWorkspaceState != Workspace.State.OVERVIEW) {
202b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            Log.e(TAG, "Unexpected call to startAnimationToWorkspace");
203b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
204b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
2059dcf0a3ef7595f58aedec7773e7bc3b9075fb3caHyunyoung Song        if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED
2069dcf0a3ef7595f58aedec7773e7bc3b9075fb3caHyunyoung Song                || mAllAppsController.isTransitioning()) {
207645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            int animType = CIRCULAR_REVEAL;
208645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
209645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                animType = PULLUP;
210645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            }
2112a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            startAnimationToWorkspaceFromAllApps(fromWorkspaceState, toWorkspaceState,
212645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    animated, animType, onCompleteRunnable);
2136d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else if (fromState == Launcher.State.WIDGETS ||
2146d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                fromState == Launcher.State.WIDGETS_SPRING_LOADED) {
2152a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            startAnimationToWorkspaceFromWidgets(fromWorkspaceState, toWorkspaceState,
216dc61c4d41468a8beced2863de1b863b340cf49baWinson Chung                    animated, onCompleteRunnable);
2176d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else {
2186d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            startAnimationToNewWorkspaceState(fromWorkspaceState, toWorkspaceState,
2196d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    animated, onCompleteRunnable);
220b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
221b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
222b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
223b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
224b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Creates and starts a new animation to a particular overlay view.
225b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
226191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song    private void startAnimationToOverlay(
227db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            final Workspace.State toWorkspaceState,
2280ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View buttonView, final BaseContainerView toView,
229645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final boolean animated, int animType, final PrivateTransitionCallbacks pCb) {
230006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
231b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final Resources res = mLauncher.getResources();
2329fc953b94dbc6b99e6de08c9dcc80a0cb8e3e319Sunny Goyal        final boolean material = Utilities.ATLEAST_LOLLIPOP;
2335f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
234e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song        final int revealDurationSlide = res.getInteger(R.integer.config_overlaySlideRevealTime);
235e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song
2360ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        final int itemsAlphaStagger = res.getInteger(R.integer.config_overlayItemsAlphaStagger);
237b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
238b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
239b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
240b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // If for some reason our views aren't initialized, don't animate
24198ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        boolean initialized = buttonView != null;
242b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
243b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // Cancel the current animation
244b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        cancelAnimation();
245b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
2460ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        final View contentView = toView.getContentView();
247db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState,
24861d9e78f23efcf43be1945d4233780ac89db99d9Winson                animated, initialized, animation, layerViews);
249645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (!animated || !initialized) {
250ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song            if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP &&
251ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song                    toWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
252ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song                mAllAppsController.finishPullUp();
253ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song            }
254645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setTranslationX(0.0f);
255645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setTranslationY(0.0f);
256645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setScaleX(1.0f);
257645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setScaleY(1.0f);
258645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setAlpha(1.0f);
259645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setVisibility(View.VISIBLE);
260645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
261645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            // Show the content view
262645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            contentView.setVisibility(View.VISIBLE);
263645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            pCb.onTransitionComplete();
264191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            return;
265645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
266645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (animType == CIRCULAR_REVEAL) {
267b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Setup the reveal view animation
2680ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View revealView = toView.getRevealView();
2690ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
270b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            int width = revealView.getMeasuredWidth();
271b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            int height = revealView.getMeasuredHeight();
272f7a29e83f06909b378dba39c83a522375682710aSunny Goyal            float revealRadius = (float) Math.hypot(width / 2, height / 2);
273b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setVisibility(View.VISIBLE);
274b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setAlpha(0f);
275b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setTranslationY(0f);
276b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setTranslationX(0f);
277b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
278b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Calculate the final animation values
279b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            final float revealViewToAlpha;
280b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            final float revealViewToXDrift;
281b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            final float revealViewToYDrift;
282b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            if (material) {
2830ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(
2840ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                        revealView, buttonView, null);
2850ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                revealViewToAlpha = pCb.materialRevealViewFinalAlpha;
28698ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                revealViewToYDrift = buttonViewToPanelDelta[1];
28798ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                revealViewToXDrift = buttonViewToPanelDelta[0];
288b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            } else {
289b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealViewToAlpha = 0f;
290b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealViewToYDrift = 2 * height / 3;
291b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealViewToXDrift = 0;
292b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
293b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
294b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Create the animators
295b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelAlpha =
2965d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.ALPHA, revealViewToAlpha, 1f);
297b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelDriftY =
2985d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, revealViewToYDrift, 0);
299b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelDriftX =
3005d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.TRANSLATION_X, revealViewToXDrift, 0);
301b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator panelAlphaAndDrift = ObjectAnimator.ofPropertyValuesHolder(revealView,
302b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    panelAlpha, panelDriftY, panelDriftX);
303b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            panelAlphaAndDrift.setDuration(revealDuration);
304b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
305b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
306b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Play the animation
307b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(revealView);
308006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(panelAlphaAndDrift);
309b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
310b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Setup the animation for the content view
311b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setVisibility(View.VISIBLE);
312b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setAlpha(0f);
313b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setTranslationY(revealViewToYDrift);
314b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(contentView);
315b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
316b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Create the individual animators
317b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator pageDrift = ObjectAnimator.ofFloat(contentView, "translationY",
318b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    revealViewToYDrift, 0);
319b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setDuration(revealDuration);
320b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
321b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setStartDelay(itemsAlphaStagger);
322006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(pageDrift);
323b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
324b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 0f, 1f);
325b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setDuration(revealDuration);
326b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
327b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setStartDelay(itemsAlphaStagger);
328006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(itemsAlpha);
329b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
330b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            if (material) {
331b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                float startRadius = pCb.getMaterialRevealViewStartFinalRadius();
332b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                AnimatorListenerAdapter listener = pCb.getMaterialRevealViewAnimatorListener(
33398ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                        revealView, buttonView);
3348f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham                Animator reveal = new CircleRevealOutlineProvider(width / 2, height / 2,
3358f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham                        startRadius, revealRadius).createRevealAnimator(revealView);
336b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                reveal.setDuration(revealDuration);
337b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
338b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                if (listener != null) {
339b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    reveal.addListener(listener);
340b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
341006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(reveal);
342b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
343b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
344006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.addListener(new AnimatorListenerAdapter() {
345b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                @Override
346b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                public void onAnimationEnd(Animator animation) {
347b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Hide the reveal view
348b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    revealView.setVisibility(View.INVISIBLE);
349b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
350b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // This can hold unnecessary references to views.
351006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    cleanupAnimation();
35276648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                    pCb.onTransitionComplete();
353b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
354b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
355b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            });
356b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
357b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            toView.bringToFront();
358b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            toView.setVisibility(View.VISIBLE);
359b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal
360b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            animation.addListener(layerViews);
361db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            toView.post(new StartAnimRunnable(animation, toView));
362191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
363645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        } else if (animType == PULLUP) {
36461d9e78f23efcf43be1945d4233780ac89db99d9Winson            // We are animating the content view alpha, so ensure we have a layer for it
365b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(contentView);
36661d9e78f23efcf43be1945d4233780ac89db99d9Winson
367645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            animation.addListener(new AnimatorListenerAdapter() {
368191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                @Override
369191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                public void onAnimationEnd(Animator animation) {
370191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                    cleanupAnimation();
371191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                    pCb.onTransitionComplete();
372191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                }
373645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            });
374191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            boolean shouldPost = mAllAppsController.animateToAllApps(animation, revealDurationSlide);
375b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
376db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Runnable startAnimRunnable = new StartAnimRunnable(animation, toView);
377191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
378b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
379191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            if (shouldPost) {
380191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                toView.post(startAnimRunnable);
381191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            } else {
382191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                startAnimRunnable.run();
383191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            }
384b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
385b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
386b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
387b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
388685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham     * Plays animations used by various transitions.
389685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham     */
3907c50b31f57e3e3ec1f433d243afe05554dcaf977Sunny Goyal    private void playCommonTransitionAnimations(
391db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Workspace.State toWorkspaceState,
39261d9e78f23efcf43be1945d4233780ac89db99d9Winson            boolean animated, boolean initialized, AnimatorSet animation,
393b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            AnimationLayerSet layerViews) {
394685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        // Create the workspace animation.
395685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        // NOTE: this call apparently also sets the state for the workspace if !animated
396685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState,
397685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham                animated, layerViews);
398685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham
399685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        if (animated && initialized) {
400685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            // Play the workspace animation
401685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            if (workspaceAnim != null) {
402685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham                animation.play(workspaceAnim);
403685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            }
404685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        }
405685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham    }
406685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham
407685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham    /**
4086d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the apps view.
409b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
410006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    private void startAnimationToWorkspaceFromAllApps(final Workspace.State fromWorkspaceState,
411645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final Workspace.State toWorkspaceState, final boolean animated, int type,
4122a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final Runnable onCompleteRunnable) {
413db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        final AllAppsContainerView appsView = mLauncher.getAppsView();
4140ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        // No alpha anim from all apps
4150ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks(1f) {
416b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
417b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            float getMaterialRevealViewStartFinalRadius() {
4182e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
419b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return allAppsButtonSize / 2;
420b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
421b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
422b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
423b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    final View revealView, final View allAppsButtonView) {
424b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
425b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationStart(Animator animation) {
426b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // We set the alpha instead of visibility to ensure that the focus does not
427b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // get taken from the all apps view
428b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.VISIBLE);
429b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setAlpha(0f);
430b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
431b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
432b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Hide the reveal view
433b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        revealView.setVisibility(View.INVISIBLE);
434b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
435b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Show the all apps button, and focus it
436b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setAlpha(1f);
437b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
438b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
439b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
4408fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            @Override
4418fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            void onTransitionComplete() {
442aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
443db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal                appsView.reset();
4448fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            }
445b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
446ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Only animate the search bar if animating to spring loaded mode from all apps
447191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        startAnimationToWorkspaceFromOverlay(fromWorkspaceState, toWorkspaceState,
448bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal                mLauncher.getStartViewForAllAppsRevealAnimation(), appsView,
449645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                animated, type, onCompleteRunnable, cb);
450b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
451b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
452b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
4536d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the widgets view.
454b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
455006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    private void startAnimationToWorkspaceFromWidgets(final Workspace.State fromWorkspaceState,
4566d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Workspace.State toWorkspaceState, final boolean animated,
4572a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final Runnable onCompleteRunnable) {
4584cea4c830283e017fc36197cfe9d7ce713aec49dHyunyoung Song        final WidgetsContainerView widgetsView = mLauncher.getWidgetsView();
4590ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb =
4600ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS) {
461b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
462b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
46398ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                    final View revealView, final View widgetsButtonView) {
464b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
465b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
466b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Hide the reveal view
467b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        revealView.setVisibility(View.INVISIBLE);
468b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
469b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
470b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
4718fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            @Override
4728fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            void onTransitionComplete() {
473aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
4748fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            }
475b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
476191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        startAnimationToWorkspaceFromOverlay(
4770ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                fromWorkspaceState, toWorkspaceState,
4787c50b31f57e3e3ec1f433d243afe05554dcaf977Sunny Goyal                mLauncher.getWidgetsButton(), widgetsView,
479645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                animated, CIRCULAR_REVEAL, onCompleteRunnable, cb);
480b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
481b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
482b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
4836d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from another workspace state, e.g. normal to overview.
4846d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     */
4856d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    private void startAnimationToNewWorkspaceState(final Workspace.State fromWorkspaceState,
4866d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Workspace.State toWorkspaceState, final boolean animated,
4876d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Runnable onCompleteRunnable) {
4886d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        final View fromWorkspace = mLauncher.getWorkspace();
489b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
4906d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
4916d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
4926d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        // Cancel the current animation
4936d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        cancelAnimation();
4946d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
495db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState, animated, animated, animation, layerViews);
496f3e35d93318190f995e6a0fc9d0441ac844b67e4Jon Miranda        mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
497f3e35d93318190f995e6a0fc9d0441ac844b67e4Jon Miranda
4986d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        if (animated) {
4996d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            animation.addListener(new AnimatorListenerAdapter() {
5006d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                @Override
5016d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                public void onAnimationEnd(Animator animation) {
5026d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    // Run any queued runnables
5036d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    if (onCompleteRunnable != null) {
5046d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                        onCompleteRunnable.run();
5056d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    }
5066d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
5076d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    // This can hold unnecessary references to views.
5086d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    cleanupAnimation();
5096d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                }
5106d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            });
511db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            animation.addListener(layerViews);
512db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            fromWorkspace.post(new StartAnimRunnable(animation, null));
5136d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            mCurrentAnimation = animation;
5146d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else /* if (!animated) */ {
5156d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            // Run any queued runnables
5166d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            if (onCompleteRunnable != null) {
5176d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                onCompleteRunnable.run();
5186d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            }
5196d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
5206d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            mCurrentAnimation = null;
5216d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        }
5226d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    }
5236d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
5246d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    /**
525b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Creates and starts a new animation to the workspace.
526b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
527191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song    private void startAnimationToWorkspaceFromOverlay(
5280ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
5290ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View buttonView, final BaseContainerView fromView,
530645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final boolean animated, int animType, final Runnable onCompleteRunnable,
531006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            final PrivateTransitionCallbacks pCb) {
532006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
533b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final Resources res = mLauncher.getResources();
5349fc953b94dbc6b99e6de08c9dcc80a0cb8e3e319Sunny Goyal        final boolean material = Utilities.ATLEAST_LOLLIPOP;
5355f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
536e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song        final int revealDurationSlide = res.getInteger(R.integer.config_overlaySlideRevealTime);
537b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final int itemsAlphaStagger =
5385f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung                res.getInteger(R.integer.config_overlayItemsAlphaStagger);
539b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
540b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final View toView = mLauncher.getWorkspace();
54161d9e78f23efcf43be1945d4233780ac89db99d9Winson        final View revealView = fromView.getRevealView();
54261d9e78f23efcf43be1945d4233780ac89db99d9Winson        final View contentView = fromView.getContentView();
543b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
544b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
545b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
546b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // If for some reason our views aren't initialized, don't animate
54798ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        boolean initialized = buttonView != null;
548b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
549b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // Cancel the current animation
550b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        cancelAnimation();
551b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
552db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState,
55361d9e78f23efcf43be1945d4233780ac89db99d9Winson                animated, initialized, animation, layerViews);
55474b5af35291f620d2f09f313f2e9bd9f817b9d27Hyunyoung Song        if (!animated || !initialized) {
555ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song            if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP &&
556ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song                    fromWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
5577ccc4625e38b8107cd1882272aec36967874a5ccHyunyoung Song                mAllAppsController.finishPullDown();
558b11ae50fcb2bb07ee77645fdacdf90f67f58dae4Hyunyoung Song            }
559645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            fromView.setVisibility(View.GONE);
560645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            pCb.onTransitionComplete();
5610bb211a9d5cd4eabcbf46385bbfb9895e5cd7325Tony Wickham
562645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            // Run any queued runnables
563645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            if (onCompleteRunnable != null) {
564645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                onCompleteRunnable.run();
565645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            }
566191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            return;
567645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
568645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (animType == CIRCULAR_REVEAL) {
569b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // hideAppsCustomizeHelper is called in some cases when it is already hidden
570b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // don't perform all these no-op animations. In particularly, this was causing
571b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // the all-apps button to pop in and out.
572b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            if (fromView.getVisibility() == View.VISIBLE) {
573b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                int width = revealView.getMeasuredWidth();
574b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                int height = revealView.getMeasuredHeight();
575f7a29e83f06909b378dba39c83a522375682710aSunny Goyal                float revealRadius = (float) Math.hypot(width / 2, height / 2);
576b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setVisibility(View.VISIBLE);
577b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setAlpha(1f);
578b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setTranslationY(0);
579b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal                layerViews.addView(revealView);
580b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
581b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Calculate the final animation values
582b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                final float revealViewToXDrift;
583b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                final float revealViewToYDrift;
584b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                if (material) {
58598ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                    int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
58698ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                            buttonView, null);
58798ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                    revealViewToYDrift = buttonViewToPanelDelta[1];
58898ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                    revealViewToXDrift = buttonViewToPanelDelta[0];
589b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                } else {
590b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    revealViewToYDrift = 2 * height / 3;
591b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    revealViewToXDrift = 0;
592b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
593b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
594b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // The vertical motion of the apps panel should be delayed by one frame
595b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // from the conceal animation in order to give the right feel. We correspondingly
596b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // shorten the duration so that the slide and conceal end at the same time.
597b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                TimeInterpolator decelerateInterpolator = material ?
598b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        new LogDecelerateInterpolator(100, 0) :
599b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        new DecelerateInterpolator(1f);
6001558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator panelDriftY = ObjectAnimator.ofFloat(revealView, "translationY",
601b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToYDrift);
602b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
603b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
604b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setInterpolator(decelerateInterpolator);
605006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(panelDriftY);
606b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
6071558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator panelDriftX = ObjectAnimator.ofFloat(revealView, "translationX",
608b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToXDrift);
609b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
610b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
611b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setInterpolator(decelerateInterpolator);
612006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(panelDriftX);
613b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
614b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Setup animation for the reveal panel alpha
615b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                final float revealViewToAlpha = !material ? 0f :
6160ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                        pCb.materialRevealViewFinalAlpha;
617b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                if (revealViewToAlpha != 1f) {
6181558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                    ObjectAnimator panelAlpha = ObjectAnimator.ofFloat(revealView, "alpha",
619b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                            1f, revealViewToAlpha);
620b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    panelAlpha.setDuration(material ? revealDuration : 150);
621b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    panelAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY);
622b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    panelAlpha.setInterpolator(decelerateInterpolator);
623006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    animation.play(panelAlpha);
624b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
625b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
626b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Setup the animation for the content view
627b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal                layerViews.addView(contentView);
628b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
629b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Create the individual animators
6301558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator pageDrift = ObjectAnimator.ofFloat(contentView, "translationY",
631b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToYDrift);
632b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                contentView.setTranslationY(0);
633b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
634b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setInterpolator(decelerateInterpolator);
635b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
636006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(pageDrift);
637b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
638b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                contentView.setAlpha(1f);
6391558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 1f, 0f);
640b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                itemsAlpha.setDuration(100);
641b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                itemsAlpha.setInterpolator(decelerateInterpolator);
642006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(itemsAlpha);
643b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
6443f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                // Invalidate the scrim throughout the animation to ensure the highlight
6453f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                // cutout is correct throughout.
6463f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                ValueAnimator invalidateScrim = ValueAnimator.ofFloat(0f, 1f);
6473f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                invalidateScrim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
6483f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    @Override
6493f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    public void onAnimationUpdate(ValueAnimator animation) {
6503f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                        mLauncher.getDragLayer().invalidateScrim();
6513f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    }
6523f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                });
6533f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                animation.play(invalidateScrim);
6543f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham
655b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                if (material) {
656b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Animate the all apps button
657b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    float finalRadius = pCb.getMaterialRevealViewStartFinalRadius();
658b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    AnimatorListenerAdapter listener =
65998ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                            pCb.getMaterialRevealViewAnimatorListener(revealView, buttonView);
6608f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham                    Animator reveal = new CircleRevealOutlineProvider(width / 2, height / 2,
6618f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham                            revealRadius, finalRadius).createRevealAnimator(revealView);
662b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
663b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    reveal.setDuration(revealDuration);
664b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    reveal.setStartDelay(itemsAlphaStagger);
665b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    if (listener != null) {
666b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        reveal.addListener(listener);
667b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
668006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    animation.play(reveal);
669b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
670b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
671b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
672006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.addListener(new AnimatorListenerAdapter() {
673b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                @Override
674b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                public void onAnimationEnd(Animator animation) {
675b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    fromView.setVisibility(View.GONE);
676b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Run any queued runnables
677b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    if (onCompleteRunnable != null) {
678b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        onCompleteRunnable.run();
679b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
680b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
681b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Reset page transforms
682b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    if (contentView != null) {
683b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setTranslationX(0);
684b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setTranslationY(0);
685b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setAlpha(1);
686b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
687b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
688b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // This can hold unnecessary references to views.
689006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    cleanupAnimation();
69076648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                    pCb.onTransitionComplete();
691b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
692b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            });
693b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
694191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
695b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
696db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            fromView.post(new StartAnimRunnable(animation, null));
697645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        } else if (animType == PULLUP) {
69861d9e78f23efcf43be1945d4233780ac89db99d9Winson            // We are animating the content view alpha, so ensure we have a layer for it
699b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(contentView);
70061d9e78f23efcf43be1945d4233780ac89db99d9Winson
701645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            animation.addListener(new AnimatorListenerAdapter() {
702eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                boolean canceled = false;
703645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                @Override
704eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                public void onAnimationCancel(Animator animation) {
705eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                    canceled = true;
706645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                }
707b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
708645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                @Override
709645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                public void onAnimationEnd(Animator animation) {
710eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                    if (canceled) return;
711645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    // Run any queued runnables
712645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    if (onCompleteRunnable != null) {
713645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                        onCompleteRunnable.run();
714645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    }
71561d9e78f23efcf43be1945d4233780ac89db99d9Winson
716645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    cleanupAnimation();
717645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    pCb.onTransitionComplete();
718645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                }
719eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song
720645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            });
721191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            boolean shouldPost = mAllAppsController.animateToWorkspace(animation, revealDurationSlide);
722eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song
723db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Runnable startAnimRunnable = new StartAnimRunnable(animation, toView);
724191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
725b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
726191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            if (shouldPost) {
727191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                fromView.post(startAnimRunnable);
728191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            } else {
729191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                startAnimRunnable.run();
730191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            }
731b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
732191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        return;
733b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
734b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
735006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    /**
736b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Cancels the current animation.
737b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
738b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    private void cancelAnimation() {
739006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        if (mCurrentAnimation != null) {
740006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation.setDuration(0);
741006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation.cancel();
742006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation = null;
743b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
744b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
745006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung
746d1ea63f24a751521e6c35cc06be0e548e0b04f23Sunny Goyal    @Thunk void cleanupAnimation() {
747006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        mCurrentAnimation = null;
748006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    }
749db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
750db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    private class StartAnimRunnable implements Runnable {
751db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
752db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        private final AnimatorSet mAnim;
753db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        private final View mViewToFocus;
754db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
755db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        public StartAnimRunnable(AnimatorSet anim, View viewToFocus) {
756db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mAnim = anim;
757db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mViewToFocus = viewToFocus;
758db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        }
759db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
760db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        @Override
761db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        public void run() {
762db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            if (mCurrentAnimation != mAnim) {
763db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal                return;
764db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            }
765db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            if (mViewToFocus != null) {
766db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal                mViewToFocus.requestFocus();
767db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            }
768db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mAnim.start();
769db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        }
770db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    }
7711558893b873cd55b2df779f594f1de3c370d3328Adam Cohen}
772