1785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung/*
2785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * Copyright (C) 2011 The Android Open Source Project
3785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung *
4785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
5785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * you may not use this file except in compliance with the License.
6785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * You may obtain a copy of the License at
7785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung *
8785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
9785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung *
10785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * Unless required by applicable law or agreed to in writing, software
11785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
12785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * See the License for the specific language governing permissions and
14785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung * limitations under the License.
15785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung */
16785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
17785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungpackage com.android.launcher2;
18785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
19f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chungimport android.animation.Animator;
20b44b52439d155f570db7d6d0b80fdd3350e35685Winson Chungimport android.animation.AnimatorListenerAdapter;
21f314b0eab03bb354c14b6c89f694a6685bd246d9Winson Chungimport android.animation.AnimatorSet;
22b44b52439d155f570db7d6d0b80fdd3350e35685Winson Chungimport android.animation.ObjectAnimator;
23785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.content.Context;
24785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.content.res.Resources;
25785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.util.AttributeSet;
26785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.view.LayoutInflater;
274179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chungimport android.view.MotionEvent;
28785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.view.View;
29785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.view.ViewGroup;
30141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurkaimport android.widget.FrameLayout;
311899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurkaimport android.widget.LinearLayout;
32785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.widget.TabHost;
33faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chungimport android.widget.TabWidget;
34785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.widget.TextView;
35785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
36785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport com.android.launcher.R;
37785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
38141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurkaimport java.util.ArrayList;
39141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka
40785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungpublic class AppsCustomizeTabHost extends TabHost implements LauncherTransitionable,
41785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        TabHost.OnTabChangeListener  {
42785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    static final String LOG_TAG = "AppsCustomizeTabHost";
43785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
44785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    private static final String APPS_TAB_TAG = "APPS";
45785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    private static final String WIDGETS_TAB_TAG = "WIDGETS";
46785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
47785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    private final LayoutInflater mLayoutInflater;
48f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    private ViewGroup mTabs;
49fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung    private ViewGroup mTabsContainer;
504179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung    private AppsCustomizePagedView mAppsCustomizePane;
51141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka    private FrameLayout mAnimationBuffer;
521899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka    private LinearLayout mContent;
53785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
54c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung    private boolean mInTransition;
557044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung    private boolean mTransitioningToWorkspace;
56c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung    private boolean mResetAfterTransition;
576cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka    private Runnable mRelayoutAndMakeVisible;
58c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung
59785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
60785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        super(context, attrs);
61785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        mLayoutInflater = LayoutInflater.from(context);
626cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka        mRelayoutAndMakeVisible = new Runnable() {
636cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka                public void run() {
646cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka                    mTabs.requestLayout();
656cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka                    mTabsContainer.setAlpha(1f);
666cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka                }
676cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka            };
68785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    }
69785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
70f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    /**
715a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung     * Convenience methods to select specific tabs.  We want to set the content type immediately
725a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung     * in these cases, but we note that we still call setCurrentTabByTag() so that the tab view
735a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung     * reflects the new content (but doesn't do the animation and logic associated with changing
745a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung     * tabs manually).
75f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung     */
76c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung    void setContentTypeImmediate(AppsCustomizePagedView.ContentType type) {
77fa4086ddd7ab9dd98e3ffef798a655ec07e37e14Winson Chung        setOnTabChangedListener(null);
785a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung        onTabChangedStart();
795a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung        onTabChangedEnd(type);
80fa4086ddd7ab9dd98e3ffef798a655ec07e37e14Winson Chung        setCurrentTabByTag(getTabTagForContentType(type));
81fa4086ddd7ab9dd98e3ffef798a655ec07e37e14Winson Chung        setOnTabChangedListener(this);
825a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung    }
8355b6550e37da5df2fda44fc712bc082731f2d8e7Winson Chung    void selectAppsTab() {
845a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung        setContentTypeImmediate(AppsCustomizePagedView.ContentType.Applications);
8555b6550e37da5df2fda44fc712bc082731f2d8e7Winson Chung    }
8655b6550e37da5df2fda44fc712bc082731f2d8e7Winson Chung    void selectWidgetsTab() {
875a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung        setContentTypeImmediate(AppsCustomizePagedView.ContentType.Widgets);
885a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung    }
8955b6550e37da5df2fda44fc712bc082731f2d8e7Winson Chung
90785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    /**
91785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung     * Setup the tab host and create all necessary tabs.
92785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung     */
93785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    @Override
94785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    protected void onFinishInflate() {
95785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        // Setup the tab host
96785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        setup();
97785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
98fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung        final ViewGroup tabsContainer = (ViewGroup) findViewById(R.id.tabs_container);
998b805b17158886035b38261eb611d8641701ae43Michael Jurka        final TabWidget tabs = getTabWidget();
1004179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung        final AppsCustomizePagedView appsCustomizePane = (AppsCustomizePagedView)
101785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                findViewById(R.id.apps_customize_pane_content);
102f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        mTabs = tabs;
103fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung        mTabsContainer = tabsContainer;
1044179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung        mAppsCustomizePane = appsCustomizePane;
105141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka        mAnimationBuffer = (FrameLayout) findViewById(R.id.animation_buffer);
1061899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka        mContent = (LinearLayout) findViewById(R.id.apps_customize_content);
1074179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung        if (tabs == null || mAppsCustomizePane == null) throw new Resources.NotFoundException();
108785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
109785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        // Configure the tabs content factory to return the same paged view (that we change the
110785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        // content filter on)
111785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        TabContentFactory contentFactory = new TabContentFactory() {
112785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            public View createTabContent(String tag) {
1134179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung                return appsCustomizePane;
114785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            }
115785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        };
116785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
117785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        // Create the tabs
118785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        TextView tabView;
119d2c1f80aa73bef9d7fb5991ec29ea7a7b2e38f90Winson Chung        String label;
1208b805b17158886035b38261eb611d8641701ae43Michael Jurka        label = getContext().getString(R.string.all_apps_button_label);
121785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
122d2c1f80aa73bef9d7fb5991ec29ea7a7b2e38f90Winson Chung        tabView.setText(label);
123d2c1f80aa73bef9d7fb5991ec29ea7a7b2e38f90Winson Chung        tabView.setContentDescription(label);
124785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
1258b805b17158886035b38261eb611d8641701ae43Michael Jurka        label = getContext().getString(R.string.widgets_tab_label);
126785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
127d2c1f80aa73bef9d7fb5991ec29ea7a7b2e38f90Winson Chung        tabView.setText(label);
128d2c1f80aa73bef9d7fb5991ec29ea7a7b2e38f90Winson Chung        tabView.setContentDescription(label);
129785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
130785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        setOnTabChangedListener(this);
131faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chung
132faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chung        // Setup the key listener to jump between the last tab view and the market icon
133faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chung        AppsCustomizeTabKeyEventListener keyListener = new AppsCustomizeTabKeyEventListener();
134faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chung        View lastTab = tabs.getChildTabViewAt(tabs.getTabCount() - 1);
135faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chung        lastTab.setOnKeyListener(keyListener);
136faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chung        View shopButton = findViewById(R.id.market_button);
137faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chung        shopButton.setOnKeyListener(keyListener);
138fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung
139fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung        // Hide the tab bar until we measure
140fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung        mTabsContainer.setAlpha(0f);
141f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    }
142785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
143f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    @Override
144f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
145f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        boolean remeasureTabWidth = (mTabs.getLayoutParams().width <= 0);
146f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
147f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
148f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // Set the width of the tab list to the content width
149f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        if (remeasureTabWidth) {
150fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung            int contentWidth = mAppsCustomizePane.getPageContentWidth();
151141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka            if (contentWidth > 0 && mTabs.getLayoutParams().width != contentWidth) {
152141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // Set the width and show the tab bar
153fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung                mTabs.getLayoutParams().width = contentWidth;
154c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung                mRelayoutAndMakeVisible.run();
155fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung            }
156c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung
157c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
158f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        }
1594179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung    }
1604179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung
1617044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung     public boolean onInterceptTouchEvent(MotionEvent ev) {
162ac08f4b93e075fd90c8689509ad3108284a717d8Winson Chung         // If we are mid transitioning to the workspace, then intercept touch events here so we
163ac08f4b93e075fd90c8689509ad3108284a717d8Winson Chung         // can ignore them, otherwise we just let all apps handle the touch events.
164ac08f4b93e075fd90c8689509ad3108284a717d8Winson Chung         if (mInTransition && mTransitioningToWorkspace) {
1657044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung             return true;
1667044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung         }
1677044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung         return super.onInterceptTouchEvent(ev);
1687044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung     };
1697044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung
1704179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung    @Override
1714179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung    public boolean onTouchEvent(MotionEvent event) {
172ac08f4b93e075fd90c8689509ad3108284a717d8Winson Chung        // Allow touch events to fall through to the workspace if we are transitioning there
173ac08f4b93e075fd90c8689509ad3108284a717d8Winson Chung        if (mInTransition && mTransitioningToWorkspace) {
17421fadeaad1f5a662df425085551c6f54e8c28f52Winson Chung            return super.onTouchEvent(event);
1757044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung        }
1767044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung
1774179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung        // Intercept all touch events up to the bottom of the AppsCustomizePane so they do not fall
1784179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung        // through to the workspace and trigger showWorkspace()
1794179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung        if (event.getY() < mAppsCustomizePane.getBottom()) {
1804179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung            return true;
1814179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung        }
1824179b4e048dd019daca053dc3a7eddf6c464b08bWinson Chung        return super.onTouchEvent(event);
183785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    }
184785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
1855a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung    private void onTabChangedStart() {
1865a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung        mAppsCustomizePane.hideScrollingIndicator(false);
1875a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung    }
1880cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen
189097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung    private void reloadCurrentPage() {
190097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung        if (!LauncherApplication.isScreenLarge()) {
191b737ee6ab2dc4938a1b2a574c336af0eab826712Michael Jurka            mAppsCustomizePane.flashScrollingIndicator(true);
192097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung        }
193097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung        mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
194097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung        mAppsCustomizePane.requestFocus();
195097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung    }
196097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung
1975a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung    private void onTabChangedEnd(AppsCustomizePagedView.ContentType type) {
1985a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung        mAppsCustomizePane.setContentType(type);
1995a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung    }
2005a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung
201785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    @Override
202785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    public void onTabChanged(String tabId) {
203b44b52439d155f570db7d6d0b80fdd3350e35685Winson Chung        final AppsCustomizePagedView.ContentType type = getContentTypeForTabTag(tabId);
204b44b52439d155f570db7d6d0b80fdd3350e35685Winson Chung
2050cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen        // Animate the changing of the tab content by fading pages in and out
2060cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen        final Resources res = getResources();
2070cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen        final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
208f314b0eab03bb354c14b6c89f694a6685bd246d9Winson Chung
2090cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen        // We post a runnable here because there is a delay while the first page is loading and
2100cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen        // the feedback from having changed the tab almost feels better than having it stick
2110cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen        post(new Runnable() {
2120cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen            @Override
2130cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen            public void run() {
214097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung                if (mAppsCustomizePane.getMeasuredWidth() <= 0 ||
215097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung                        mAppsCustomizePane.getMeasuredHeight() <= 0) {
216097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung                    reloadCurrentPage();
217097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung                    return;
218097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung                }
219097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung
220141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // Take the visible pages and re-parent them temporarily to mAnimatorBuffer
221141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // and then cross fade to the new pages
222c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                int[] visiblePageRange = new int[2];
223c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                mAppsCustomizePane.getVisiblePages(visiblePageRange);
224c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                if (visiblePageRange[0] == -1 && visiblePageRange[1] == -1) {
225c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                    // If we can't get the visible page ranges, then just skip the animation
226c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                    reloadCurrentPage();
227c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                    return;
228c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                }
229c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                ArrayList<View> visiblePages = new ArrayList<View>();
230c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                for (int i = visiblePageRange[0]; i <= visiblePageRange[1]; i++) {
231c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                    visiblePages.add(mAppsCustomizePane.getPageAt(i));
232c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                }
233141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka
234141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // We want the pages to be rendered in exactly the same way as they were when
235141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // their parent was mAppsCustomizePane -- so set the scroll on mAnimationBuffer
236141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // to be exactly the same as mAppsCustomizePane, and below, set the left/top
237141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // parameters to be correct for each of the pages
238141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                mAnimationBuffer.scrollTo(mAppsCustomizePane.getScrollX(), 0);
239141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka
240141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // mAppsCustomizePane renders its children in reverse order, so
241141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                // add the pages to mAnimationBuffer in reverse order to match that behavior
242141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                for (int i = visiblePages.size() - 1; i >= 0; i--) {
243141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    View child = visiblePages.get(i);
244c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                    if (child instanceof PagedViewCellLayout) {
245c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                        ((PagedViewCellLayout) child).resetChildrenOnKeyListeners();
246c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                    } else if (child instanceof PagedViewGridLayout) {
247c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                        ((PagedViewGridLayout) child).resetChildrenOnKeyListeners();
248c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung                    }
249141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    PagedViewWidget.setDeletePreviewsWhenDetachedFromWindow(false);
250141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    mAppsCustomizePane.removeView(child);
251141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    PagedViewWidget.setDeletePreviewsWhenDetachedFromWindow(true);
252141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    mAnimationBuffer.setAlpha(1f);
253141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    mAnimationBuffer.setVisibility(View.VISIBLE);
2546e3cf9001e2cd5df1b9850831a6ce21497bd1202Winson Chung                    LayoutParams p = new FrameLayout.LayoutParams(child.getMeasuredWidth(),
2556e3cf9001e2cd5df1b9850831a6ce21497bd1202Winson Chung                            child.getMeasuredHeight());
256141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    p.setMargins((int) child.getLeft(), (int) child.getTop(), 0, 0);
257141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    mAnimationBuffer.addView(child, p);
258141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                }
259b44b52439d155f570db7d6d0b80fdd3350e35685Winson Chung
2600cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                // Toggle the new content
2610cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                onTabChangedStart();
2620cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                onTabChangedEnd(type);
2630cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen
2640cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                // Animate the transition
2652ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka                ObjectAnimator outAnim = LauncherAnimUtils.ofFloat(mAnimationBuffer, "alpha", 0f);
2660cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                outAnim.addListener(new AnimatorListenerAdapter() {
267ee8e99fe3bde78885904b4d9ea789b4d2a6f2b16Michael Jurka                    private void clearAnimationBuffer() {
2680cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                        mAnimationBuffer.setVisibility(View.GONE);
269ee8e99fe3bde78885904b4d9ea789b4d2a6f2b16Michael Jurka                        PagedViewWidget.setRecyclePreviewsWhenDetachedFromWindow(false);
270141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                        mAnimationBuffer.removeAllViews();
271ee8e99fe3bde78885904b4d9ea789b4d2a6f2b16Michael Jurka                        PagedViewWidget.setRecyclePreviewsWhenDetachedFromWindow(true);
272ee8e99fe3bde78885904b4d9ea789b4d2a6f2b16Michael Jurka                    }
273ee8e99fe3bde78885904b4d9ea789b4d2a6f2b16Michael Jurka                    @Override
274ee8e99fe3bde78885904b4d9ea789b4d2a6f2b16Michael Jurka                    public void onAnimationEnd(Animator animation) {
275ee8e99fe3bde78885904b4d9ea789b4d2a6f2b16Michael Jurka                        clearAnimationBuffer();
276141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    }
277141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    @Override
278141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka                    public void onAnimationCancel(Animator animation) {
279ee8e99fe3bde78885904b4d9ea789b4d2a6f2b16Michael Jurka                        clearAnimationBuffer();
2800cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                    }
2810cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                });
2822ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka                ObjectAnimator inAnim = LauncherAnimUtils.ofFloat(mAppsCustomizePane, "alpha", 1f);
2830cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                inAnim.addListener(new AnimatorListenerAdapter() {
2840cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                    @Override
2850cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                    public void onAnimationEnd(Animator animation) {
286097e6c71b12ad1fdc9beba5f74c466521508df9dWinson Chung                        reloadCurrentPage();
2870cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                    }
2880cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                });
2897f9ddd84353451e72f48f34a8d280d5e873b2f45Michael Jurka
2907f9ddd84353451e72f48f34a8d280d5e873b2f45Michael Jurka                final AnimatorSet animSet = LauncherAnimUtils.createAnimatorSet();
2910cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                animSet.playTogether(outAnim, inAnim);
2920cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen                animSet.setDuration(duration);
293f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka                animSet.start();
2940cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen            }
2950cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen        });
2960cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen    }
2970cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen
2980cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen    public void setCurrentTabFromContent(AppsCustomizePagedView.ContentType type) {
299fa4086ddd7ab9dd98e3ffef798a655ec07e37e14Winson Chung        setOnTabChangedListener(null);
3000cd3b64e607cc1f81ed49b00ef7398c2a2b7a48dAdam Cohen        setCurrentTabByTag(getTabTagForContentType(type));
301fa4086ddd7ab9dd98e3ffef798a655ec07e37e14Winson Chung        setOnTabChangedListener(this);
302785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    }
303785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
304785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    /**
305785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung     * Returns the content type for the specified tab tag.
306785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung     */
307785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    public AppsCustomizePagedView.ContentType getContentTypeForTabTag(String tag) {
308785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        if (tag.equals(APPS_TAB_TAG)) {
309785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            return AppsCustomizePagedView.ContentType.Applications;
310785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        } else if (tag.equals(WIDGETS_TAB_TAG)) {
311785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            return AppsCustomizePagedView.ContentType.Widgets;
312785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        }
313785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        return AppsCustomizePagedView.ContentType.Applications;
314785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    }
315785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
316785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    /**
317fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung     * Returns the tab tag for a given content type.
318fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung     */
319fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung    public String getTabTagForContentType(AppsCustomizePagedView.ContentType type) {
320fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung        if (type == AppsCustomizePagedView.ContentType.Applications) {
321fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung            return APPS_TAB_TAG;
322fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung        } else if (type == AppsCustomizePagedView.ContentType.Widgets) {
323fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung            return WIDGETS_TAB_TAG;
324fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung        }
325fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung        return APPS_TAB_TAG;
326fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung    }
327fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung
328fc79c8067e21e55fce3802a63e15ee4c6f11d595Winson Chung    /**
329785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung     * Disable focus on anything under this view in the hierarchy if we are not visible.
330785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung     */
331785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    @Override
332785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    public int getDescendantFocusability() {
333785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        if (getVisibility() != View.VISIBLE) {
334785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
335785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        }
336785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        return super.getDescendantFocusability();
337785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    }
338785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
339c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung    void reset() {
340c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung        if (mInTransition) {
341c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung            // Defer to after the transition to reset
342c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung            mResetAfterTransition = true;
343c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung        } else {
344c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung            // Reset immediately
345c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung            mAppsCustomizePane.reset();
346c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung        }
347c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung    }
348c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung
3491899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka    private void enableAndBuildHardwareLayer() {
35019e0fc53c43a7746d7ae3d7c6027166bded33f0fMichael Jurka        // isHardwareAccelerated() checks if we're attached to a window and if that
35119e0fc53c43a7746d7ae3d7c6027166bded33f0fMichael Jurka        // window is HW accelerated-- we were sometimes not attached to a window
35219e0fc53c43a7746d7ae3d7c6027166bded33f0fMichael Jurka        // and buildLayer was throwing an IllegalStateException
3531899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka        if (isHardwareAccelerated()) {
354f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            // Turn on hardware layers for performance
355f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            setLayerType(LAYER_TYPE_HARDWARE, null);
356f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
3571899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka            // force building the layer, so you don't get a blip early in an animation
3581899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka            // when the layer is created layer
359f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            buildLayer();
360f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        }
3611899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka    }
3621899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka
3632a4b1a809c6bc0af9ae3ad974fe50e2a91569543Michael Jurka    @Override
3642a4b1a809c6bc0af9ae3ad974fe50e2a91569543Michael Jurka    public View getContent() {
3652a4b1a809c6bc0af9ae3ad974fe50e2a91569543Michael Jurka        return mContent;
3661899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka    }
3671899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka
3681899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka    /* LauncherTransitionable overrides */
3691899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka    @Override
370a35e35ae0ac2391b8928eb15bf91274aea96b115Michael Jurka    public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
371a35e35ae0ac2391b8928eb15bf91274aea96b115Michael Jurka        mAppsCustomizePane.onLauncherTransitionPrepare(l, animated, toWorkspace);
3721899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka        mInTransition = true;
3737044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung        mTransitioningToWorkspace = toWorkspace;
3741899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka
375bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        if (toWorkspace) {
376bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            // Going from All Apps -> Workspace
377bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            setVisibilityOfSiblingsWithLowerZOrder(VISIBLE);
378a8352d22afd3b78ab01ded90ad1674599100fda5Michael Jurka            // Stop the scrolling indicator - we don't want All Apps to be invalidating itself
379a8352d22afd3b78ab01ded90ad1674599100fda5Michael Jurka            // during the transition, especially since it has a hardware layer set on it
380a8352d22afd3b78ab01ded90ad1674599100fda5Michael Jurka            mAppsCustomizePane.cancelScrollingIndicatorAnimations();
381bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        } else {
382bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            // Going from Workspace -> All Apps
383bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            mContent.setVisibility(VISIBLE);
3843d845e8d8921eebe0b072b7856b660b4350921e1Michael Jurka
385e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            // Make sure the current page is loaded (we start loading the side pages after the
386e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            // transition to prevent slowing down the animation)
387e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
3881899a36ab3aab7671420511f47eb8b273b9b1078Michael Jurka
389bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            if (!LauncherApplication.isScreenLarge()) {
390bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                mAppsCustomizePane.showScrollingIndicator(true);
391bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            }
392430e8a5f5b06181addfd37223518fc21c5c41b69Michael Jurka        }
393bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka
394c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung        if (mResetAfterTransition) {
395c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung            mAppsCustomizePane.reset();
396c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung            mResetAfterTransition = false;
397c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung        }
398a35e35ae0ac2391b8928eb15bf91274aea96b115Michael Jurka    }
399bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka
400a35e35ae0ac2391b8928eb15bf91274aea96b115Michael Jurka    @Override
401a35e35ae0ac2391b8928eb15bf91274aea96b115Michael Jurka    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
402bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        if (animated) {
403bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            enableAndBuildHardwareLayer();
404bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        }
405785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    }
406f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
407785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    @Override
4087044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung    public void onLauncherTransitionStep(Launcher l, float t) {
4097044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung        // Do nothing
4107044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung    }
4117044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung
4127044272f180d34ab29866f6c59ee75376e8a1df5Winson Chung    @Override
413bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
41439e5d176e6e375e7ae46d42ed14412d54cb223c9Michael Jurka        mAppsCustomizePane.onLauncherTransitionEnd(l, animated, toWorkspace);
415c100e8eae7d67ad5bd78767494b62b8fae5d1779Winson Chung        mInTransition = false;
416bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        if (animated) {
417f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            setLayerType(LAYER_TYPE_NONE, null);
418f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        }
4193ac74c55cf8baef29db80e8c67ab4ab033b04417Winson Chung
4207d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        if (!toWorkspace) {
4217819abd2d191a170cbc9d4bd190001c465187a9dWinson Chung            // Dismiss the workspace cling
4227d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung            l.dismissWorkspaceCling(null);
4237819abd2d191a170cbc9d4bd190001c465187a9dWinson Chung            // Show the all apps cling (if not already shown)
4243f4e1423804d64a38cb69e4511d7b80783564827Winson Chung            mAppsCustomizePane.showAllAppsCling();
425e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            // Make sure adjacent pages are loaded (we wait until after the transition to
426e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            // prevent slowing down the animation)
427e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
4287d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung
4297d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung            if (!LauncherApplication.isScreenLarge()) {
4307d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung                mAppsCustomizePane.hideScrollingIndicator(false);
4317d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung            }
4327819abd2d191a170cbc9d4bd190001c465187a9dWinson Chung
4337819abd2d191a170cbc9d4bd190001c465187a9dWinson Chung            // Going from Workspace -> All Apps
4347819abd2d191a170cbc9d4bd190001c465187a9dWinson Chung            // NOTE: We should do this at the end since we check visibility state in some of the
4357819abd2d191a170cbc9d4bd190001c465187a9dWinson Chung            // cling initialization/dismiss code above.
4367819abd2d191a170cbc9d4bd190001c465187a9dWinson Chung            setVisibilityOfSiblingsWithLowerZOrder(INVISIBLE);
4375a808358f1a773dab8babae44899ffd4ed1810c1Winson Chung        }
438785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung    }
43970d721061536e0634f6cfa8cd219759a83befceeWinson Chung
440bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka    private void setVisibilityOfSiblingsWithLowerZOrder(int visibility) {
441bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        ViewGroup parent = (ViewGroup) getParent();
442aea1ce51bcb218960d9a95495c3c22bc492351bfMichael Jurka        if (parent == null) return;
443aea1ce51bcb218960d9a95495c3c22bc492351bfMichael Jurka
444bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        final int count = parent.getChildCount();
445bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        if (!isChildrenDrawingOrderEnabled()) {
446bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            for (int i = 0; i < count; i++) {
447bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                final View child = parent.getChildAt(i);
448bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                if (child == this) {
449bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                    break;
450bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                } else {
451bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                    if (child.getVisibility() == GONE) {
452bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                        continue;
453bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                    }
454bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                    child.setVisibility(visibility);
455bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka                }
456bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            }
457bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        } else {
458bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka            throw new RuntimeException("Failed; can't get z-order of views");
459bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka        }
460bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka    }
461bed61d22bdbfcdbe04f92675c7751b83c7a8947cMichael Jurka
4622a4b1a809c6bc0af9ae3ad974fe50e2a91569543Michael Jurka    public void onWindowVisible() {
463e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka        if (getVisibility() == VISIBLE) {
464e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            mContent.setVisibility(VISIBLE);
465e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            // We unload the widget previews when the UI is hidden, so need to reload pages
466e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            // Load the current page synchronously, and the neighboring pages asynchronously
467e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
468e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
469e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka        }
470e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka    }
471e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka
472e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka    public void onTrimMemory() {
473e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka        mContent.setVisibility(GONE);
474e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka        // Clear the widget pages of all their subviews - this will trigger the widget previews
475e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka        // to delete their bitmaps
476e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka        mAppsCustomizePane.clearAllWidgetPages();
477e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka    }
478e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka
47970d721061536e0634f6cfa8cd219759a83befceeWinson Chung    boolean isTransitioning() {
48070d721061536e0634f6cfa8cd219759a83befceeWinson Chung        return mInTransition;
48170d721061536e0634f6cfa8cd219759a83befceeWinson Chung    }
482785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung}
483