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;
34645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.config.FeatureFlags;
358f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickhamimport com.android.launcher3.util.CircleRevealOutlineProvider;
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    /**
83645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     * animation used for all apps and widget tray when
84645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     *{@link FeatureFlags#LAUNCHER3_ALL_APPS_PULL_UP} is {@code false}
85645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     */
86645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public static final int CIRCULAR_REVEAL = 0;
87645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    /**
88645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     * animation used for all apps and not widget tray when
89645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     *{@link FeatureFlags#LAUNCHER3_ALL_APPS_PULL_UP} is {@code true}
90645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song     */
91645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public static final int PULLUP = 1;
92645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
930ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    private static final float FINAL_REVEAL_ALPHA_FOR_WIDGETS = 0.3f;
940ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
95b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
96b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Private callbacks made during transition setup.
97b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
980ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    private static class PrivateTransitionCallbacks {
990ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        private final float materialRevealViewFinalAlpha;
1000ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
1010ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks(float revealAlpha) {
1020ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            materialRevealViewFinalAlpha = revealAlpha;
103b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
1040ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
105b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        float getMaterialRevealViewStartFinalRadius() {
106b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            return 0;
107b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
108b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(View revealView,
10998ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                View buttonView) {
110b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            return null;
111b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
11276648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung        void onTransitionComplete() {}
113b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
114b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
1150ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public static final String TAG = "LSTAnimation";
116b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
117b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    public static final int SINGLE_FRAME_DELAY = 16;
118b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
119091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk Launcher mLauncher;
120006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    @Thunk AnimatorSet mCurrentAnimation;
121645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    AllAppsTransitionController mAllAppsController;
122b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
123645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public LauncherStateTransitionAnimation(Launcher l, AllAppsTransitionController allAppsController) {
124b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        mLauncher = l;
125645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mAllAppsController = allAppsController;
126b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
127b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
128b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
129b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Starts an animation to the apps view.
13076648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung     *
13176648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung     * @param startSearchAfterTransition Immediately starts app search after the transition to
13276648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung     *                                   All Apps is completed.
133b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
134db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    public void startAnimationToAllApps(
135006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            final boolean animated, final boolean startSearchAfterTransition) {
1365f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final AllAppsContainerView toView = mLauncher.getAppsView();
137bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal        final View buttonView = mLauncher.getStartViewForAllAppsRevealAnimation();
1380ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks(1f) {
139b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
140b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public float getMaterialRevealViewStartFinalRadius() {
1412e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
142b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return allAppsButtonSize / 2;
143b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
144b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
145b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
146b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    final View revealView, final View allAppsButtonView) {
147b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
148b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationStart(Animator animation) {
149b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.INVISIBLE);
150b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
151b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
152b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.VISIBLE);
153b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
154b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
155b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
15676648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            @Override
15776648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            void onTransitionComplete() {
158aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
15976648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                if (startSearchAfterTransition) {
16076648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                    toView.startAppsSearch();
16176648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                }
16276648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung            }
163b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
164645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        int animType = CIRCULAR_REVEAL;
165645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
166645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            animType = PULLUP;
167645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
168ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Only animate the search bar if animating from spring loaded mode back to all apps
169db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        startAnimationToOverlay(
170645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, animType, cb);
171b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
172b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
173b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
174b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Starts an animation to the widgets view.
175b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
176db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    public void startAnimationToWidgets(final boolean animated) {
1773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        final WidgetsContainerView toView = mLauncher.getWidgetsView();
17898ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        final View buttonView = mLauncher.getWidgetsButton();
179db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        startAnimationToOverlay(
180645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, animated, CIRCULAR_REVEAL,
1818fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS){
1828fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    @Override
1838fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    void onTransitionComplete() {
184aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                        mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
1858fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                    }
1868fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song                });
187b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
188b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
189b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
1906d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the current overlay view.
191b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
192b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    public void startAnimationToWorkspace(final Launcher.State fromState,
193006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
1942a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final boolean animated, final Runnable onCompleteRunnable) {
195b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        if (toWorkspaceState != Workspace.State.NORMAL &&
196b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                toWorkspaceState != Workspace.State.SPRING_LOADED &&
197b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                toWorkspaceState != Workspace.State.OVERVIEW) {
198b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            Log.e(TAG, "Unexpected call to startAnimationToWorkspace");
199b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
200b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
2019dcf0a3ef7595f58aedec7773e7bc3b9075fb3caHyunyoung Song        if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED
2029dcf0a3ef7595f58aedec7773e7bc3b9075fb3caHyunyoung Song                || mAllAppsController.isTransitioning()) {
203645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            int animType = CIRCULAR_REVEAL;
204645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
205645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                animType = PULLUP;
206645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            }
2072a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            startAnimationToWorkspaceFromAllApps(fromWorkspaceState, toWorkspaceState,
208645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    animated, animType, onCompleteRunnable);
2096d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else if (fromState == Launcher.State.WIDGETS ||
2106d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                fromState == Launcher.State.WIDGETS_SPRING_LOADED) {
2112a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            startAnimationToWorkspaceFromWidgets(fromWorkspaceState, toWorkspaceState,
212dc61c4d41468a8beced2863de1b863b340cf49baWinson Chung                    animated, onCompleteRunnable);
2136d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else {
2146d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            startAnimationToNewWorkspaceState(fromWorkspaceState, toWorkspaceState,
2156d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    animated, onCompleteRunnable);
216b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
217b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
218b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
219b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
220b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Creates and starts a new animation to a particular overlay view.
221b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
222191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song    private void startAnimationToOverlay(
223db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            final Workspace.State toWorkspaceState,
2240ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View buttonView, final BaseContainerView toView,
225645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final boolean animated, int animType, final PrivateTransitionCallbacks pCb) {
226006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
227b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final Resources res = mLauncher.getResources();
2285f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
229e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song        final int revealDurationSlide = res.getInteger(R.integer.config_overlaySlideRevealTime);
230e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song
2310ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        final int itemsAlphaStagger = res.getInteger(R.integer.config_overlayItemsAlphaStagger);
232b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
233b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
234b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
235b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // If for some reason our views aren't initialized, don't animate
23698ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        boolean initialized = buttonView != null;
237b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
238b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // Cancel the current animation
239b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        cancelAnimation();
240b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
2410ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        final View contentView = toView.getContentView();
242db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState,
24361d9e78f23efcf43be1945d4233780ac89db99d9Winson                animated, initialized, animation, layerViews);
244645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (!animated || !initialized) {
245ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song            if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP &&
246ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song                    toWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
247ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song                mAllAppsController.finishPullUp();
248ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song            }
249645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setTranslationX(0.0f);
250645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setTranslationY(0.0f);
251645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setScaleX(1.0f);
252645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setScaleY(1.0f);
253645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setAlpha(1.0f);
254645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            toView.setVisibility(View.VISIBLE);
255645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
256645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            // Show the content view
257645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            contentView.setVisibility(View.VISIBLE);
258645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            pCb.onTransitionComplete();
259191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            return;
260645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
261645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (animType == CIRCULAR_REVEAL) {
262b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Setup the reveal view animation
2630ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View revealView = toView.getRevealView();
2640ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
265b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            int width = revealView.getMeasuredWidth();
266b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            int height = revealView.getMeasuredHeight();
267f7a29e83f06909b378dba39c83a522375682710aSunny Goyal            float revealRadius = (float) Math.hypot(width / 2, height / 2);
268b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setVisibility(View.VISIBLE);
269b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setAlpha(0f);
270b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setTranslationY(0f);
271b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            revealView.setTranslationX(0f);
272b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
273b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Calculate the final animation values
274a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            int[] buttonViewToPanelDelta =
275a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    Utilities.getCenterDeltaInScreenSpace(revealView, buttonView);
276a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            final float revealViewToAlpha = pCb.materialRevealViewFinalAlpha;
277a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            final float revealViewToXDrift = buttonViewToPanelDelta[0];
278a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            final float revealViewToYDrift = buttonViewToPanelDelta[1];
279b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
280b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Create the animators
281b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelAlpha =
2825d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.ALPHA, revealViewToAlpha, 1f);
283b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelDriftY =
2845d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, revealViewToYDrift, 0);
285b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            PropertyValuesHolder panelDriftX =
2865d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                    PropertyValuesHolder.ofFloat(View.TRANSLATION_X, revealViewToXDrift, 0);
287b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator panelAlphaAndDrift = ObjectAnimator.ofPropertyValuesHolder(revealView,
288b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    panelAlpha, panelDriftY, panelDriftX);
289b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            panelAlphaAndDrift.setDuration(revealDuration);
290b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
291b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
292b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Play the animation
293b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(revealView);
294006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(panelAlphaAndDrift);
295b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
296b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Setup the animation for the content view
297b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setVisibility(View.VISIBLE);
298b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setAlpha(0f);
299b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            contentView.setTranslationY(revealViewToYDrift);
300b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(contentView);
301b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
302b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // Create the individual animators
303b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator pageDrift = ObjectAnimator.ofFloat(contentView, "translationY",
304b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    revealViewToYDrift, 0);
305b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setDuration(revealDuration);
306b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
307b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            pageDrift.setStartDelay(itemsAlphaStagger);
308006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(pageDrift);
309b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
310b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 0f, 1f);
311b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setDuration(revealDuration);
312b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
313b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            itemsAlpha.setStartDelay(itemsAlphaStagger);
314006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.play(itemsAlpha);
315b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
316a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            float startRadius = pCb.getMaterialRevealViewStartFinalRadius();
317a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            AnimatorListenerAdapter listener = pCb.getMaterialRevealViewAnimatorListener(
318a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    revealView, buttonView);
319a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            Animator reveal = new CircleRevealOutlineProvider(width / 2, height / 2,
320a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    startRadius, revealRadius).createRevealAnimator(revealView);
321a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            reveal.setDuration(revealDuration);
322a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
323a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            if (listener != null) {
324a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                reveal.addListener(listener);
325b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
326a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            animation.play(reveal);
327b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
328006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.addListener(new AnimatorListenerAdapter() {
329b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                @Override
330b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                public void onAnimationEnd(Animator animation) {
331b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Hide the reveal view
332b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    revealView.setVisibility(View.INVISIBLE);
333b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
334b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // This can hold unnecessary references to views.
335006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    cleanupAnimation();
33676648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                    pCb.onTransitionComplete();
337b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
338b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
339b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            });
340b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
341b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            toView.bringToFront();
342b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            toView.setVisibility(View.VISIBLE);
343b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal
344b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            animation.addListener(layerViews);
345db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            toView.post(new StartAnimRunnable(animation, toView));
346191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
347645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        } else if (animType == PULLUP) {
34861d9e78f23efcf43be1945d4233780ac89db99d9Winson            // We are animating the content view alpha, so ensure we have a layer for it
349b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(contentView);
35061d9e78f23efcf43be1945d4233780ac89db99d9Winson
351645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            animation.addListener(new AnimatorListenerAdapter() {
352191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                @Override
353191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                public void onAnimationEnd(Animator animation) {
354191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                    cleanupAnimation();
355191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                    pCb.onTransitionComplete();
356191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                }
357645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            });
358191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            boolean shouldPost = mAllAppsController.animateToAllApps(animation, revealDurationSlide);
359b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
360db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Runnable startAnimRunnable = new StartAnimRunnable(animation, toView);
361191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
362b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
363191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            if (shouldPost) {
364191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                toView.post(startAnimRunnable);
365191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            } else {
366191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                startAnimRunnable.run();
367191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            }
368b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
369b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
370b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
371b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
372685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham     * Plays animations used by various transitions.
373685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham     */
3747c50b31f57e3e3ec1f433d243afe05554dcaf977Sunny Goyal    private void playCommonTransitionAnimations(
375db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Workspace.State toWorkspaceState,
37661d9e78f23efcf43be1945d4233780ac89db99d9Winson            boolean animated, boolean initialized, AnimatorSet animation,
377b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            AnimationLayerSet layerViews) {
378685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        // Create the workspace animation.
379685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        // NOTE: this call apparently also sets the state for the workspace if !animated
380685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState,
381685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham                animated, layerViews);
382685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham
383685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        if (animated && initialized) {
384685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            // Play the workspace animation
385685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            if (workspaceAnim != null) {
386685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham                animation.play(workspaceAnim);
387685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham            }
388685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham        }
389685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham    }
390685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham
391685726b504d8bff913d0a51860bbda9142f7aeb5Tony Wickham    /**
3926d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the apps view.
393b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
394006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    private void startAnimationToWorkspaceFromAllApps(final Workspace.State fromWorkspaceState,
395645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final Workspace.State toWorkspaceState, final boolean animated, int type,
3962a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final Runnable onCompleteRunnable) {
397db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        final AllAppsContainerView appsView = mLauncher.getAppsView();
3980ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        // No alpha anim from all apps
3990ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks(1f) {
400b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
401b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            float getMaterialRevealViewStartFinalRadius() {
4022e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
403b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return allAppsButtonSize / 2;
404b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
405b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
406b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
407b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    final View revealView, final View allAppsButtonView) {
408b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
409b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationStart(Animator animation) {
410b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // We set the alpha instead of visibility to ensure that the focus does not
411b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // get taken from the all apps view
412b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setVisibility(View.VISIBLE);
413b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setAlpha(0f);
414b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
415b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
416b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Hide the reveal view
417b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        revealView.setVisibility(View.INVISIBLE);
418b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
419b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Show the all apps button, and focus it
420b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        allAppsButtonView.setAlpha(1f);
421b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
422b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
423b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
4248fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            @Override
4258fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            void onTransitionComplete() {
426aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
427db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal                appsView.reset();
4288fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            }
429b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
430ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Only animate the search bar if animating to spring loaded mode from all apps
431191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        startAnimationToWorkspaceFromOverlay(fromWorkspaceState, toWorkspaceState,
432bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal                mLauncher.getStartViewForAllAppsRevealAnimation(), appsView,
433645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                animated, type, onCompleteRunnable, cb);
434b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
435b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
436b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
4376d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from the widgets view.
438b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
439006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    private void startAnimationToWorkspaceFromWidgets(final Workspace.State fromWorkspaceState,
4406d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Workspace.State toWorkspaceState, final boolean animated,
4412a87fe8c41338e746c6959d992edfeb9cb00bcc1Winson            final Runnable onCompleteRunnable) {
4424cea4c830283e017fc36197cfe9d7ce713aec49dHyunyoung Song        final WidgetsContainerView widgetsView = mLauncher.getWidgetsView();
4430ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        PrivateTransitionCallbacks cb =
4440ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS) {
445b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            @Override
446b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
44798ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song                    final View revealView, final View widgetsButtonView) {
448b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                return new AnimatorListenerAdapter() {
449b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    public void onAnimationEnd(Animator animation) {
450b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        // Hide the reveal view
451b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        revealView.setVisibility(View.INVISIBLE);
452b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
453b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                };
454b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
4558fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            @Override
4568fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            void onTransitionComplete() {
457aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
4588fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song            }
459b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        };
460191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        startAnimationToWorkspaceFromOverlay(
4610ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                fromWorkspaceState, toWorkspaceState,
4627c50b31f57e3e3ec1f433d243afe05554dcaf977Sunny Goyal                mLauncher.getWidgetsButton(), widgetsView,
463645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                animated, CIRCULAR_REVEAL, onCompleteRunnable, cb);
464b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
465b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
466b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    /**
4676d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     * Starts an animation to the workspace from another workspace state, e.g. normal to overview.
4686d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham     */
4696d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    private void startAnimationToNewWorkspaceState(final Workspace.State fromWorkspaceState,
4706d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Workspace.State toWorkspaceState, final boolean animated,
4716d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            final Runnable onCompleteRunnable) {
4726d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        final View fromWorkspace = mLauncher.getWorkspace();
473b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
4746d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
4756d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
4766d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        // Cancel the current animation
4776d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        cancelAnimation();
4786d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
479db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState, animated, animated, animation, layerViews);
480f3e35d93318190f995e6a0fc9d0441ac844b67e4Jon Miranda        mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
481f3e35d93318190f995e6a0fc9d0441ac844b67e4Jon Miranda
4826d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        if (animated) {
4836d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            animation.addListener(new AnimatorListenerAdapter() {
4846d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                @Override
4856d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                public void onAnimationEnd(Animator animation) {
4866d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    // Run any queued runnables
4876d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    if (onCompleteRunnable != null) {
4886d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                        onCompleteRunnable.run();
4896d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    }
4906d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
4916d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    // This can hold unnecessary references to views.
4926d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                    cleanupAnimation();
4936d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                }
4946d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            });
495db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            animation.addListener(layerViews);
496db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            fromWorkspace.post(new StartAnimRunnable(animation, null));
4976d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            mCurrentAnimation = animation;
4986d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        } else /* if (!animated) */ {
4996d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            // Run any queued runnables
5006d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            if (onCompleteRunnable != null) {
5016d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham                onCompleteRunnable.run();
5026d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            }
5036d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
5046d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham            mCurrentAnimation = null;
5056d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham        }
5066d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    }
5076d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham
5086d1bbe350f0e37e99ec31b4ab480cc83f0b0c5dcTony Wickham    /**
509b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Creates and starts a new animation to the workspace.
510b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
511191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song    private void startAnimationToWorkspaceFromOverlay(
5120ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
5130ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            final View buttonView, final BaseContainerView fromView,
514645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            final boolean animated, int animType, final Runnable onCompleteRunnable,
515006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            final PrivateTransitionCallbacks pCb) {
516006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
517b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final Resources res = mLauncher.getResources();
5185f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung        final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
519e3876e8dd0a6b6948c5365af9f88709301bbb536Hyunyoung Song        final int revealDurationSlide = res.getInteger(R.integer.config_overlaySlideRevealTime);
520a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal        final int itemsAlphaStagger = res.getInteger(R.integer.config_overlayItemsAlphaStagger);
521b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
522b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        final View toView = mLauncher.getWorkspace();
52361d9e78f23efcf43be1945d4233780ac89db99d9Winson        final View revealView = fromView.getRevealView();
52461d9e78f23efcf43be1945d4233780ac89db99d9Winson        final View contentView = fromView.getContentView();
525b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
526b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal        final AnimationLayerSet layerViews = new AnimationLayerSet();
527b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
528b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // If for some reason our views aren't initialized, don't animate
52998ff38aa48b4c9d3e33c128fae2d5c851e49a3ebHyunyoung Song        boolean initialized = buttonView != null;
530b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
531b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        // Cancel the current animation
532b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        cancelAnimation();
533b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
534db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        playCommonTransitionAnimations(toWorkspaceState,
53561d9e78f23efcf43be1945d4233780ac89db99d9Winson                animated, initialized, animation, layerViews);
53674b5af35291f620d2f09f313f2e9bd9f817b9d27Hyunyoung Song        if (!animated || !initialized) {
537ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song            if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP &&
538ca7f30f7cfdbea155cbef701485718fa5dd86f46Hyunyoung Song                    fromWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
5397ccc4625e38b8107cd1882272aec36967874a5ccHyunyoung Song                mAllAppsController.finishPullDown();
540b11ae50fcb2bb07ee77645fdacdf90f67f58dae4Hyunyoung Song            }
541645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            fromView.setVisibility(View.GONE);
542645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            pCb.onTransitionComplete();
5430bb211a9d5cd4eabcbf46385bbfb9895e5cd7325Tony Wickham
544645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            // Run any queued runnables
545645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            if (onCompleteRunnable != null) {
546645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                onCompleteRunnable.run();
547645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            }
548191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            return;
549645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
550645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (animType == CIRCULAR_REVEAL) {
551b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // hideAppsCustomizeHelper is called in some cases when it is already hidden
552b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // don't perform all these no-op animations. In particularly, this was causing
553b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            // the all-apps button to pop in and out.
554b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            if (fromView.getVisibility() == View.VISIBLE) {
555b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                int width = revealView.getMeasuredWidth();
556b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                int height = revealView.getMeasuredHeight();
557f7a29e83f06909b378dba39c83a522375682710aSunny Goyal                float revealRadius = (float) Math.hypot(width / 2, height / 2);
558b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setVisibility(View.VISIBLE);
559b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setAlpha(1f);
560b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                revealView.setTranslationY(0);
561b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal                layerViews.addView(revealView);
562b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
563b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Calculate the final animation values
564a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView, buttonView);
565a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                final float revealViewToXDrift = buttonViewToPanelDelta[0];
566a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                final float revealViewToYDrift = buttonViewToPanelDelta[1];
567b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
568b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // The vertical motion of the apps panel should be delayed by one frame
569b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // from the conceal animation in order to give the right feel. We correspondingly
570b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // shorten the duration so that the slide and conceal end at the same time.
571a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                TimeInterpolator decelerateInterpolator = new LogDecelerateInterpolator(100, 0);
5721558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator panelDriftY = ObjectAnimator.ofFloat(revealView, "translationY",
573b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToYDrift);
574b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
575b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
576b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftY.setInterpolator(decelerateInterpolator);
577006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(panelDriftY);
578b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
5791558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator panelDriftX = ObjectAnimator.ofFloat(revealView, "translationX",
580b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToXDrift);
581b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
582b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
583b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                panelDriftX.setInterpolator(decelerateInterpolator);
584006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(panelDriftX);
585b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
586b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Setup animation for the reveal panel alpha
587a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                if (pCb.materialRevealViewFinalAlpha != 1f) {
5881558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                    ObjectAnimator panelAlpha = ObjectAnimator.ofFloat(revealView, "alpha",
589a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                            1f, pCb.materialRevealViewFinalAlpha);
590a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    panelAlpha.setDuration(revealDuration);
591b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    panelAlpha.setInterpolator(decelerateInterpolator);
592006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    animation.play(panelAlpha);
593b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
594b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
595b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Setup the animation for the content view
596b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal                layerViews.addView(contentView);
597b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
598b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                // Create the individual animators
5991558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator pageDrift = ObjectAnimator.ofFloat(contentView, "translationY",
600b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        0, revealViewToYDrift);
601b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                contentView.setTranslationY(0);
602b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
603b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setInterpolator(decelerateInterpolator);
604b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
605006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(pageDrift);
606b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
607b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                contentView.setAlpha(1f);
6081558893b873cd55b2df779f594f1de3c370d3328Adam Cohen                ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 1f, 0f);
609b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                itemsAlpha.setDuration(100);
610b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                itemsAlpha.setInterpolator(decelerateInterpolator);
611006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                animation.play(itemsAlpha);
612b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
6133f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                // Invalidate the scrim throughout the animation to ensure the highlight
6143f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                // cutout is correct throughout.
6153f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                ValueAnimator invalidateScrim = ValueAnimator.ofFloat(0f, 1f);
6163f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                invalidateScrim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
6173f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    @Override
6183f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    public void onAnimationUpdate(ValueAnimator animation) {
6193f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                        mLauncher.getDragLayer().invalidateScrim();
6203f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                    }
6213f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                });
6223f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham                animation.play(invalidateScrim);
6233f6c0ee7f5c75410dfe9e05f31fdb71b21ceecd3Tony Wickham
624a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                // Animate the all apps button
625a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                float finalRadius = pCb.getMaterialRevealViewStartFinalRadius();
626a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                AnimatorListenerAdapter listener =
627a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                        pCb.getMaterialRevealViewAnimatorListener(revealView, buttonView);
628a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                Animator reveal = new CircleRevealOutlineProvider(width / 2, height / 2,
629a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                        revealRadius, finalRadius).createRevealAnimator(revealView);
630a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
631a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                reveal.setDuration(revealDuration);
632a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                reveal.setStartDelay(itemsAlphaStagger);
633a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                if (listener != null) {
634a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                    reveal.addListener(listener);
635b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
636a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal                animation.play(reveal);
637b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            }
638b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
639006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            animation.addListener(new AnimatorListenerAdapter() {
640b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                @Override
641b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                public void onAnimationEnd(Animator animation) {
642b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    fromView.setVisibility(View.GONE);
643b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Run any queued runnables
644b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    if (onCompleteRunnable != null) {
645b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        onCompleteRunnable.run();
646b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
647b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
648b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // Reset page transforms
649b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    if (contentView != null) {
650b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setTranslationX(0);
651b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setTranslationY(0);
652b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                        contentView.setAlpha(1);
653b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    }
654b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
655b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                    // This can hold unnecessary references to views.
656006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung                    cleanupAnimation();
65776648c58d5fe8e5c0695f865243d3f421c53a84dWinson Chung                    pCb.onTransitionComplete();
658b745afbdd75157c73d581b345118cdaff99e912dWinson Chung                }
659b745afbdd75157c73d581b345118cdaff99e912dWinson Chung            });
660b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
661191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
662b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
663db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            fromView.post(new StartAnimRunnable(animation, null));
664645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        } else if (animType == PULLUP) {
66561d9e78f23efcf43be1945d4233780ac89db99d9Winson            // We are animating the content view alpha, so ensure we have a layer for it
666b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            layerViews.addView(contentView);
66761d9e78f23efcf43be1945d4233780ac89db99d9Winson
668645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            animation.addListener(new AnimatorListenerAdapter() {
669eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                boolean canceled = false;
670645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                @Override
671eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                public void onAnimationCancel(Animator animation) {
672eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                    canceled = true;
673645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                }
674b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
675645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                @Override
676645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                public void onAnimationEnd(Animator animation) {
677eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song                    if (canceled) return;
678645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    // Run any queued runnables
679645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    if (onCompleteRunnable != null) {
680645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                        onCompleteRunnable.run();
681645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    }
68261d9e78f23efcf43be1945d4233780ac89db99d9Winson
683645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    cleanupAnimation();
684645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                    pCb.onTransitionComplete();
685645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song                }
686eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song
687645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            });
688191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            boolean shouldPost = mAllAppsController.animateToWorkspace(animation, revealDurationSlide);
689eac1dac23944ea5127dc12a161f016f18a5599cbHyunyoung Song
690db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            Runnable startAnimRunnable = new StartAnimRunnable(animation, toView);
691191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            mCurrentAnimation = animation;
692b5e65c8bd3785409d4aeda21f2c88e75c9e22c9fSunny Goyal            mCurrentAnimation.addListener(layerViews);
693191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            if (shouldPost) {
694191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                fromView.post(startAnimRunnable);
695191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            } else {
696191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song                startAnimRunnable.run();
697191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song            }
698b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
699191e9d1b297f3a5dd2953f00c9cf9eac364fcf69Hyunyoung Song        return;
700b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
701b745afbdd75157c73d581b345118cdaff99e912dWinson Chung
702006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    /**
703b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     * Cancels the current animation.
704b745afbdd75157c73d581b345118cdaff99e912dWinson Chung     */
705b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    private void cancelAnimation() {
706006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        if (mCurrentAnimation != null) {
707006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation.setDuration(0);
708006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation.cancel();
709006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung            mCurrentAnimation = null;
710b745afbdd75157c73d581b345118cdaff99e912dWinson Chung        }
711b745afbdd75157c73d581b345118cdaff99e912dWinson Chung    }
712006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung
713d1ea63f24a751521e6c35cc06be0e548e0b04f23Sunny Goyal    @Thunk void cleanupAnimation() {
714006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        mCurrentAnimation = null;
715006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung    }
716db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
717db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    private class StartAnimRunnable implements Runnable {
718db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
719db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        private final AnimatorSet mAnim;
720db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        private final View mViewToFocus;
721db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
722db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        public StartAnimRunnable(AnimatorSet anim, View viewToFocus) {
723db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mAnim = anim;
724db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mViewToFocus = viewToFocus;
725db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        }
726db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal
727db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        @Override
728db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        public void run() {
729db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            if (mCurrentAnimation != mAnim) {
730db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal                return;
731db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            }
732db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            if (mViewToFocus != null) {
733db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal                mViewToFocus.requestFocus();
734db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            }
735db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal            mAnim.start();
736db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal        }
737db364379312e56a3a3905a54d0de783062a92a73Sunny Goyal    }
7381558893b873cd55b2df779f594f1de3c370d3328Adam Cohen}
739