FolderPagedView.java revision a1fbd84b791474a9e86b67caeaf27b8429afba73
1290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal/**
2290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * Copyright (C) 2015 The Android Open Source Project
3290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal *
4290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * Licensed under the Apache License, Version 2.0 (the "License");
5290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * you may not use this file except in compliance with the License.
6290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * You may obtain a copy of the License at
7290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal *
8290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal *      http://www.apache.org/licenses/LICENSE-2.0
9290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal *
10290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * Unless required by applicable law or agreed to in writing, software
11290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * distributed under the License is distributed on an "AS IS" BASIS,
12290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * See the License for the specific language governing permissions and
14290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * limitations under the License.
15290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal */
16290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
17290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalpackage com.android.launcher3;
18290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
19e4766230ff8115c5897ebee74c145bcae822581eSunny Goyalimport android.annotation.SuppressLint;
20290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.content.Context;
21290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.util.AttributeSet;
22290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.util.Log;
23b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyalimport android.view.Gravity;
24290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.view.LayoutInflater;
25290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.view.View;
264846193300245c8c0a1f9bde3175f273df044309Sunny Goyalimport android.view.animation.DecelerateInterpolator;
27b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyalimport android.view.animation.OvershootInterpolator;
28290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
29290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport com.android.launcher3.FocusHelper.PagedFolderKeyEventListener;
30290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport com.android.launcher3.PageIndicator.PageMarkerResources;
31290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport com.android.launcher3.Workspace.ItemOperator;
32091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
33290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
34290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport java.util.ArrayList;
35290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport java.util.HashMap;
36290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport java.util.Iterator;
374846193300245c8c0a1f9bde3175f273df044309Sunny Goyalimport java.util.Map;
38290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
39b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyalpublic class FolderPagedView extends PagedView {
40290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
41290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private static final String TAG = "FolderPagedView";
42290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
43b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    private static final boolean ALLOW_FOLDER_SCROLL = true;
44b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal
45290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private static final int REORDER_ANIMATION_DURATION = 230;
464846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    private static final int START_VIEW_REORDER_DELAY = 30;
474846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    private static final float VIEW_REORDER_DELAY_FACTOR = 0.9f;
485d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
49b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    private static final int PAGE_INDICATOR_ANIMATION_DELAY = 150;
50b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal
513b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    /**
523b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal     * Fraction of the width to scroll when showing the next page hint.
533b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal     */
543b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    private static final float SCROLL_HINT_FRACTION = 0.07f;
553b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
56290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private static final int[] sTempPosArray = new int[2];
57290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
587066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal    public final boolean mIsRtl;
593b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
60290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private final LayoutInflater mInflater;
61290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private final IconCache mIconCache;
62091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen
63091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final HashMap<View, Runnable> mPendingAnimations = new HashMap<>();
64290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
65e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxCountX;
66e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxCountY;
67e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxItemsPerPage;
68290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
69290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mAllocatedContentSize;
70290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mGridCountX;
71290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mGridCountY;
72290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
73290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private Folder mFolder;
74290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private FocusIndicatorView mFocusIndicatorView;
75290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private PagedFolderKeyEventListener mKeyListener;
76290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
77b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    private PageIndicator mPageIndicator;
785d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
79290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public FolderPagedView(Context context, AttributeSet attrs) {
80290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        super(context, attrs);
81290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        LauncherAppState app = LauncherAppState.getInstance();
82290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
83290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
84fee35bbfac29a55382880f846fff86003e615ccbSunny Goyal        mMaxCountX = (int) grid.numFolderColumns;
85fee35bbfac29a55382880f846fff86003e615ccbSunny Goyal        mMaxCountY = (int) grid.numFolderRows;
86b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal
87290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mMaxItemsPerPage = mMaxCountX * mMaxCountY;
88290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
89290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mInflater = LayoutInflater.from(context);
90290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mIconCache = app.getIconCache();
913b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
927066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal        mIsRtl = Utilities.isRtl(getResources());
93db184fdc7bd652e45216a453541ab4a266457a3aSunny Goyal        setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
94290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
95290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
96290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFolder(Folder folder) {
97290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mFolder = folder;
98290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mFocusIndicatorView = (FocusIndicatorView) folder.findViewById(R.id.focus_indicator);
99290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mKeyListener = new PagedFolderKeyEventListener(folder);
100b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        mPageIndicator = (PageIndicator) folder.findViewById(R.id.folder_page_indicator);
101290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
102290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
103290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
104290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Sets up the grid size such that {@param count} items can fit in the grid.
105290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * The grid size is calculated such that countY <= countX and countX = ceil(sqrt(count)) while
106290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * maintaining the restrictions of {@link #mMaxCountX} &amp; {@link #mMaxCountY}.
107290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
108290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private void setupContentDimensions(int count) {
109290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mAllocatedContentSize = count;
110290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        boolean done;
111290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (count >= mMaxItemsPerPage) {
112290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            mGridCountX = mMaxCountX;
113290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            mGridCountY = mMaxCountY;
114290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            done = true;
115290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
116290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            done = false;
117290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
118290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
119290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (!done) {
120290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int oldCountX = mGridCountX;
121290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int oldCountY = mGridCountY;
122290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (mGridCountX * mGridCountY < count) {
123290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Current grid is too small, expand it
124290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                if ((mGridCountX <= mGridCountY || mGridCountY == mMaxCountY) && mGridCountX < mMaxCountX) {
125290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    mGridCountX++;
126290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                } else if (mGridCountY < mMaxCountY) {
127290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    mGridCountY++;
128290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
129290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                if (mGridCountY == 0) mGridCountY++;
130290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            } else if ((mGridCountY - 1) * mGridCountX >= count && mGridCountY >= mGridCountX) {
131290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                mGridCountY = Math.max(0, mGridCountY - 1);
132290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            } else if ((mGridCountX - 1) * mGridCountY >= count) {
133290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                mGridCountX = Math.max(0, mGridCountX - 1);
134290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
135290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            done = mGridCountX == oldCountX && mGridCountY == oldCountY;
136290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
137290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
138e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        // Update grid size
139e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        for (int i = getPageCount() - 1; i >= 0; i--) {
140290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            getPageAt(i).setGridSize(mGridCountX, mGridCountY);
141290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
142290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
143290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
144b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
145b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Binds items to the layout.
146b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * @return list of items that could not be bound, probably because we hit the max size limit.
147b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
148290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> items) {
149e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        ArrayList<View> icons = new ArrayList<View>();
150b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        ArrayList<ShortcutInfo> extra = new ArrayList<ShortcutInfo>();
151b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal
152290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (ShortcutInfo item : items) {
153b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal            if (!ALLOW_FOLDER_SCROLL && icons.size() >= mMaxItemsPerPage) {
154b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal                extra.add(item);
155b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal            } else {
156b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal                icons.add(createNewView(item));
157b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal            }
158290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
159e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        arrangeChildren(icons, icons.size(), false);
160b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        return extra;
161290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
162290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
163290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
164290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Create space for a new item at the end, and returns the rank for that item.
165290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Also sets the current page to the last page.
166290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
1675d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal    public int allocateRankForNewItem(ShortcutInfo info) {
168290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int rank = getItemCount();
1695d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        ArrayList<View> views = new ArrayList<View>(mFolder.getItemsInReadingOrder());
1705d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        views.add(rank, null);
1715d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        arrangeChildren(views, views.size(), false);
1725d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        setCurrentPage(rank / mMaxItemsPerPage);
173290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return rank;
174290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
175290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
176290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View createAndAddViewForRank(ShortcutInfo item, int rank) {
177e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        View icon = createNewView(item);
1785d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        addViewForRank(icon, item, rank);
179e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        return icon;
180290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
181290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
182b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
183b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Adds the {@param view} to the layout based on {@param rank} and updated the position
184b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * related attributes. It assumes that {@param item} is already attached to the view.
185b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
186290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void addViewForRank(View view, ShortcutInfo item, int rank) {
187e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        int pagePos = rank % mMaxItemsPerPage;
188e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        int pageNo = rank / mMaxItemsPerPage;
189290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
190290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        item.rank = rank;
191290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        item.cellX = pagePos % mGridCountX;
192290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        item.cellY = pagePos / mGridCountX;
193290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
194e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
195e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        lp.cellX = item.cellX;
196e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        lp.cellY = item.cellY;
197e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        getPageAt(pageNo).addViewToCellLayout(
198e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                view, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true);
199290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
200290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
201e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    @SuppressLint("InflateParams")
202b8c663c492d32963b6ee33750fc985f037c58f10Sunny Goyal    public View createNewView(ShortcutInfo item) {
203290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        final BubbleTextView textView = (BubbleTextView) mInflater.inflate(
204e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                R.layout.folder_application, null, false);
205dfaccf64bd59343de483b12eee6db61c960aedceSunny Goyal        textView.applyFromShortcutInfo(item, mIconCache);
206290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        textView.setOnClickListener(mFolder);
207290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        textView.setOnLongClickListener(mFolder);
208290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        textView.setOnFocusChangeListener(mFocusIndicatorView);
209290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        textView.setOnKeyListener(mKeyListener);
210290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
211e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        textView.setLayoutParams(new CellLayout.LayoutParams(
212e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                item.cellX, item.cellY, item.spanX, item.spanY));
213290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return textView;
214290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
215290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
216290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
217290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public CellLayout getPageAt(int index) {
218290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return (CellLayout) getChildAt(index);
219290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
220290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
221290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void removeCellLayoutView(View view) {
222290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = getChildCount() - 1; i >= 0; i --) {
223290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            getPageAt(i).removeView(view);
224290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
225290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
226290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
227290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public CellLayout getCurrentCellLayout() {
228290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return getPageAt(getNextPage());
229290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
230290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
231e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private CellLayout createAndAddNewPage() {
232290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        DeviceProfile grid = LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile();
233e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        CellLayout page = new CellLayout(getContext());
234e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
235e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
236db184fdc7bd652e45216a453541ab4a266457a3aSunny Goyal        page.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
237e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setInvertIfRtl(true);
238e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setGridSize(mGridCountX, mGridCountY);
239290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
24022fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        addView(page, -1, generateDefaultLayoutParams());
241e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        return page;
242290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
243290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
244a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    @Override
245a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    protected int getChildGap() {
246a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal        return getPaddingLeft() + getPaddingRight();
247a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    }
248a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal
249290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFixedSize(int width, int height) {
25022fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        width -= (getPaddingLeft() + getPaddingRight());
25122fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        height -= (getPaddingTop() + getPaddingBottom());
252290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = getChildCount() - 1; i >= 0; i --) {
253290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            ((CellLayout) getChildAt(i)).setFixedSize(width, height);
254290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
255290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
256290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
257290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void removeItem(View v) {
258290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = getChildCount() - 1; i >= 0; i --) {
259290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            getPageAt(i).removeView(v);
260290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
261290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
262290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
263290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
264290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Updates position and rank of all the children in the view.
265290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * It essentially removes all views from all the pages and then adds them again in appropriate
266290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * page.
267290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     *
268290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * @param list the ordered list of children.
269290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * @param itemCount if greater than the total children count, empty spaces are left
270290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * at the end, otherwise it is ignored.
271290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     *
272290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
273290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void arrangeChildren(ArrayList<View> list, int itemCount) {
274e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        arrangeChildren(list, itemCount, true);
275e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    }
276e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal
277e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private void arrangeChildren(ArrayList<View> list, int itemCount, boolean saveChanges) {
278290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        ArrayList<CellLayout> pages = new ArrayList<CellLayout>();
279290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = 0; i < getChildCount(); i++) {
280290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            CellLayout page = (CellLayout) getChildAt(i);
281290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            page.removeAllViews();
282290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            pages.add(page);
283290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
284290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        setupContentDimensions(itemCount);
285290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
286290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        Iterator<CellLayout> pageItr = pages.iterator();
287290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout currentPage = null;
288290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
289290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int position = 0;
290290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int newX, newY, rank;
291290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
292290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        rank = 0;
2934846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        for (int i = 0; i < itemCount; i++) {
2944846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            View v = list.size() > i ? list.get(i) : null;
295290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (currentPage == null || position >= mMaxItemsPerPage) {
296290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Next page
297290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                if (pageItr.hasNext()) {
298290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    currentPage = pageItr.next();
299290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                } else {
300e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                    currentPage = createAndAddNewPage();
301290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
302290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                position = 0;
303290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
304290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
3054846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            if (v != null) {
3064846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
3074846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                newX = position % mGridCountX;
3084846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                newY = position / mGridCountX;
3094846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                ItemInfo info = (ItemInfo) v.getTag();
3104846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                if (info.cellX != newX || info.cellY != newY || info.rank != rank) {
3114846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.cellX = newX;
3124846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.cellY = newY;
3134846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.rank = rank;
3144846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    if (saveChanges) {
3154846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                        LauncherModel.addOrMoveItemInDatabase(getContext(), info,
3164846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                                mFolder.mInfo.id, 0, info.cellX, info.cellY);
3174846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    }
318e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                }
3194846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                lp.cellX = info.cellX;
3204846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                lp.cellY = info.cellY;
3214846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                currentPage.addViewToCellLayout(
3224846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                        v, -1, mFolder.mLauncher.getViewIdForItem(info), lp, true);
323290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
3244846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
325290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            rank ++;
326290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            position++;
327290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
328290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
329e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        // Remove extra views.
330290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        boolean removed = false;
331290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (pageItr.hasNext()) {
332e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal            removeView(pageItr.next());
333e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal            removed = true;
334290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
335290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (removed) {
336290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            setCurrentPage(0);
337290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
3385d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
339b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        setEnableOverscroll(getPageCount() > 1);
3405d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
3415d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        // Update footer
3428167dc2dcffbf4f68724bc1db2f5cfc1caf6a848Sunny Goyal        mPageIndicator.setVisibility(getPageCount() > 1 ? View.VISIBLE : View.GONE);
343b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        mFolder.mFolderName.setGravity(getPageCount() > 1 ? Gravity.START : Gravity.CENTER_HORIZONTAL);
344290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
345290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
346290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getDesiredWidth() {
34722fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        return getPageCount() > 0 ?
34822fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal                (getPageAt(0).getDesiredWidth() + getPaddingLeft() + getPaddingRight()) : 0;
349290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
350290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
351290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getDesiredHeight()  {
35222fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        return  getPageCount() > 0 ?
35322fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal                (getPageAt(0).getDesiredHeight() + getPaddingTop() + getPaddingBottom()) : 0;
354290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
355290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
356290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getItemCount() {
357e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        int lastPageIndex = getChildCount() - 1;
358e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        if (lastPageIndex < 0) {
359e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal            // If there are no pages, nothing has yet been added to the folder.
360e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal            return 0;
3614846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
362e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        return getPageAt(lastPageIndex).getShortcutsAndWidgets().getChildCount()
363e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal                + lastPageIndex * mMaxItemsPerPage;
364290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
365290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
366b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
367b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * @return the rank of the cell nearest to the provided pixel position.
368b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
369290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int findNearestArea(int pixelX, int pixelY) {
370290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageIndex = getNextPage();
371290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout page = getPageAt(pageIndex);
372f7a29e83f06909b378dba39c83a522375682710aSunny Goyal        page.findNearestArea(pixelX, pixelY, 1, 1, sTempPosArray);
373290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mFolder.isLayoutRtl()) {
374290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            sTempPosArray[0] = page.getCountX() - sTempPosArray[0] - 1;
375290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
376290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return Math.min(mAllocatedContentSize - 1,
377290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                pageIndex * mMaxItemsPerPage + sTempPosArray[1] * mGridCountX + sTempPosArray[0]);
378290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
379290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
380290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
381290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    protected PageMarkerResources getPageIndicatorMarker(int pageIndex) {
382d3d37090c485359e2cf62eb6aa8e70350d161689Sunny Goyal        return new PageMarkerResources(R.drawable.ic_pageindicator_current_folder,
383d3d37090c485359e2cf62eb6aa8e70350d161689Sunny Goyal                R.drawable.ic_pageindicator_default_folder);
384290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
385290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
386290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public boolean isFull() {
387b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        return !ALLOW_FOLDER_SCROLL && getItemCount() >= mMaxItemsPerPage;
388290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
389290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
390290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View getLastItem() {
391290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (getChildCount() < 1) {
392290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return null;
393290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
394290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        ShortcutAndWidgetContainer lastContainer = getCurrentCellLayout().getShortcutsAndWidgets();
395290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int lastRank = lastContainer.getChildCount() - 1;
396290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mGridCountX > 0) {
397290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return lastContainer.getChildAt(lastRank % mGridCountX, lastRank / mGridCountX);
398290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
399290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return lastContainer.getChildAt(lastRank);
400290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
401290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
402290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
403b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
404b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Iterates over all its items in a reading order.
405b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * @return the view for which the operator returned true.
406b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
407290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View iterateOverItems(ItemOperator op) {
408290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int k = 0 ; k < getChildCount(); k++) {
409290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            CellLayout page = getPageAt(k);
410290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            for (int j = 0; j < page.getCountY(); j++) {
411290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                for (int i = 0; i < page.getCountX(); i++) {
412290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    View v = page.getChildAt(i, j);
413290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    if ((v != null) && op.evaluate((ItemInfo) v.getTag(), v, this)) {
414290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        return v;
415290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    }
416290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
417290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
418290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
419290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return null;
420290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
421290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
422290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public String getAccessibilityDescription() {
423290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return String.format(getContext().getString(R.string.folder_opened),
424290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                mGridCountX, mGridCountY);
425290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
426290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
427b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
428b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Sets the focus on the first visible child.
429b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
430290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFocusOnFirstChild() {
431290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        View firstChild = getCurrentCellLayout().getChildAt(0, 0);
432290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (firstChild != null) {
433290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            firstChild.requestFocus();
434290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
435290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
436290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
437290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
438290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    protected void notifyPageSwitchListener() {
439290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        super.notifyPageSwitchListener();
440290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mFolder != null) {
441290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            mFolder.updateTextViewFocus();
442290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
443290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
444290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
4454846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    /**
4464846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     * Scrolls the current view by a fraction
4474846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     */
4483b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    public void showScrollHint(int direction) {
4497066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal        float fraction = (direction == DragController.SCROLL_LEFT) ^ mIsRtl
4503b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal                ? -SCROLL_HINT_FRACTION : SCROLL_HINT_FRACTION;
4514846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int hint = (int) (fraction * getWidth());
4524846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int scroll = getScrollForPage(getNextPage()) + hint;
4534846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int delta = scroll - mUnboundedScrollX;
4544846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        if (delta != 0) {
4554846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            mScroller.setInterpolator(new DecelerateInterpolator());
4564846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, Folder.SCROLL_HINT_DURATION);
4574846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            invalidate();
4584846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
4594846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
4604846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
4614846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public void clearScrollHint() {
4624846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        if (mUnboundedScrollX != getScrollForPage(getNextPage())) {
4634846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            snapToPage(getNextPage());
4644846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
4654846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
4664846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
4674846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    /**
4684846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     * Finish animation all the views which are animating across pages
4694846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     */
4704846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public void completePendingPageChanges() {
4715d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        if (!mPendingAnimations.isEmpty()) {
4725d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal            HashMap<View, Runnable> pendingViews = new HashMap<>(mPendingAnimations);
4734846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            for (Map.Entry<View, Runnable> e : pendingViews.entrySet()) {
4744846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                e.getKey().animate().cancel();
4754846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                e.getValue().run();
4764846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            }
4774846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
4784846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
4794846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
4804846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public boolean rankOnCurrentPage(int rank) {
4814846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int p = rank / mMaxItemsPerPage;
4824846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        return p == getNextPage();
4834846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
4844846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
485290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
48634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    protected void onPageBeginMoving() {
48734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        super.onPageBeginMoving();
48834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        getVisiblePages(sTempPosArray);
48934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        for (int i = sTempPosArray[0]; i <= sTempPosArray[1]; i++) {
49034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            verifyVisibleHighResIcons(i);
49134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        }
49234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
49334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
49434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    /**
49534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     * Ensures that all the icons on the given page are of high-res
49634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     */
49734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    public void verifyVisibleHighResIcons(int pageNo) {
49834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        CellLayout page = getPageAt(pageNo);
49934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        if (page != null) {
50034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            ShortcutAndWidgetContainer parent = page.getShortcutsAndWidgets();
50134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            for (int i = parent.getChildCount() - 1; i >= 0; i--) {
50234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                ((BubbleTextView) parent.getChildAt(i)).verifyHighRes();
50334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            }
50434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        }
50534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
50634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
507ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    public int getAllocatedContentSize() {
508ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal        return mAllocatedContentSize;
509ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
510ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
511b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
512b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Reorders the items such that the {@param empty} spot moves to {@param target}
513b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
514290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void realTimeReorder(int empty, int target) {
5154846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        completePendingPageChanges();
516290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int delay = 0;
5174846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        float delayAmount = START_VIEW_REORDER_DELAY;
518290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
519290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        // Animation only happens on the current page.
520290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageToAnimate = getNextPage();
521290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
522290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageT = target / mMaxItemsPerPage;
523290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pagePosT = target % mMaxItemsPerPage;
524290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
525290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (pageT != pageToAnimate) {
526290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            Log.e(TAG, "Cannot animate when the target cell is invisible");
527290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
528290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pagePosE = empty % mMaxItemsPerPage;
529290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageE = empty / mMaxItemsPerPage;
530290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
531290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int startPos, endPos;
532290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int moveStart, moveEnd;
533290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int direction;
534290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
535290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (target == empty) {
536290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // No animation
537290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return;
538290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else if (target > empty) {
539290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // Items will move backwards to make room for the empty cell.
540290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            direction = 1;
541290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
542290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // If empty cell is in a different page, move them instantly.
543290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (pageE < pageToAnimate) {
544290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = empty;
545290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Instantly move the first item in the current page.
546290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveEnd = pageToAnimate * mMaxItemsPerPage;
547290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Animate the 2nd item in the current page, as the first item was already moved to
548290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // the last page.
549290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = 0;
550290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            } else {
551290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = moveEnd = -1;
552290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = pagePosE;
553290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
554290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
555290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            endPos = pagePosT;
556290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
557290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // The items will move forward.
558290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            direction = -1;
559290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
560290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (pageE > pageToAnimate) {
561290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Move the items immediately.
562290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = empty;
563290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Instantly move the last item in the current page.
564290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveEnd = (pageToAnimate + 1) * mMaxItemsPerPage - 1;
565290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
566290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Animations start with the second last item in the page
567290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = mMaxItemsPerPage - 1;
568290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            } else {
569290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = moveEnd = -1;
570290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = pagePosE;
571290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
572290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
573290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            endPos = pagePosT;
574290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
575290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
576290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        // Instant moving views.
577290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (moveStart != moveEnd) {
578290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int rankToMove = moveStart + direction;
579290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int p = rankToMove / mMaxItemsPerPage;
580290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int pagePos = rankToMove % mMaxItemsPerPage;
581290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int x = pagePos % mGridCountX;
582290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int y = pagePos / mGridCountX;
583290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
584290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            final CellLayout page = getPageAt(p);
585290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            final View v = page.getChildAt(x, y);
586290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (v != null) {
587290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                if (pageToAnimate != p) {
588290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    page.removeView(v);
589290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    addViewForRank(v, (ShortcutInfo) v.getTag(), moveStart);
590290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                } else {
591290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    // Do a fake animation before removing it.
592290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    final int newRank = moveStart;
593290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    final float oldTranslateX = v.getTranslationX();
594290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
595290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    Runnable endAction = new Runnable() {
596290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
597290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        @Override
598290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        public void run() {
5995d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                            mPendingAnimations.remove(v);
600290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                            v.setTranslationX(oldTranslateX);
601290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                            ((CellLayout) v.getParent().getParent()).removeView(v);
602290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                            addViewForRank(v, (ShortcutInfo) v.getTag(), newRank);
603290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        }
604290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    };
605290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    v.animate()
6067066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal                        .translationXBy((direction > 0 ^ mIsRtl) ? -v.getWidth() : v.getWidth())
607290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        .setDuration(REORDER_ANIMATION_DURATION)
608290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        .setStartDelay(0)
609290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        .withEndAction(endAction);
6105d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                    mPendingAnimations.put(v, endAction);
611290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
612290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
613290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            moveStart = rankToMove;
614290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
615290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
616290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if ((endPos - startPos) * direction <= 0) {
617290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // No animation
618290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return;
619290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
620290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
621290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout page = getPageAt(pageToAnimate);
622290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = startPos; i != endPos; i += direction) {
623290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int nextPos = i + direction;
624290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            View v = page.getChildAt(nextPos % mGridCountX, nextPos / mGridCountX);
625290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (v != null) {
626290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                ((ItemInfo) v.getTag()).rank -= direction;
627290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
628290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (page.animateChildToPosition(v, i % mGridCountX, i / mGridCountX,
629290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    REORDER_ANIMATION_DURATION, delay, true, true)) {
630290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                delay += delayAmount;
6314846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                delayAmount *= VIEW_REORDER_DELAY_FACTOR;
632290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
633290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
634290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
635b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal
636b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    public void setMarkerScale(float scale) {
637b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        int count  = mPageIndicator.getChildCount();
638b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        for (int i = 0; i < count; i++) {
639b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal            View marker = mPageIndicator.getChildAt(i);
640b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal            marker.animate().cancel();
641b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal            marker.setScaleX(scale);
642b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal            marker.setScaleY(scale);
643b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        }
644b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    }
645b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal
646b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    public void animateMarkers() {
647b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        int count  = mPageIndicator.getChildCount();
648b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        OvershootInterpolator interpolator = new OvershootInterpolator(4);
649b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        for (int i = 0; i < count; i++) {
650b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal            mPageIndicator.getChildAt(i).animate().scaleX(1).scaleY(1)
651b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal                .setInterpolator(interpolator)
652b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal                .setDuration(Folder.FOOTER_ANIMATION_DURATION)
653b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal                .setStartDelay(PAGE_INDICATOR_ANIMATION_DELAY * i);
654b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        }
655b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    }
656b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal
657b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    public int itemsPerPage() {
658b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        return mMaxItemsPerPage;
659b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    }
660290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal}
661