FolderPagedView.java revision 655ec42ce50e18f2ce597901707057b5898e110a
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
17f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenpackage com.android.launcher3.folder;
18290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
19e4766230ff8115c5897ebee74c145bcae822581eSunny Goyalimport android.annotation.SuppressLint;
20290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.content.Context;
213333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyalimport android.graphics.Canvas;
22290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.util.AttributeSet;
23290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.util.Log;
24b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyalimport android.view.Gravity;
25290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.view.LayoutInflater;
26290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.view.View;
274ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyalimport android.view.ViewDebug;
284846193300245c8c0a1f9bde3175f273df044309Sunny Goyalimport android.view.animation.DecelerateInterpolator;
29290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
30f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.BubbleTextView;
31f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.CellLayout;
32f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.DeviceProfile;
33290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport com.android.launcher3.FocusHelper.PagedFolderKeyEventListener;
34f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.InvariantDeviceProfile;
35f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.ItemInfo;
36f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.Launcher;
37f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.LauncherAppState;
38f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.LauncherModel;
39f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.PagedView;
40f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.R;
41f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.ShortcutAndWidgetContainer;
42f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.ShortcutInfo;
43f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.Utilities;
44290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport com.android.launcher3.Workspace.ItemOperator;
453333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyalimport com.android.launcher3.keyboard.ViewGroupFocusHelper;
466e74e899d314663415f54895227bb79a51fd734bTony Wickhamimport com.android.launcher3.pageindicators.PageIndicator;
471f3f07d47c29cba3b70bcd15ebb65a077f55a558Sunny Goyalimport com.android.launcher3.util.Themes;
48091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
49290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
50290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport java.util.ArrayList;
51290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport java.util.HashMap;
52290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport java.util.Iterator;
534846193300245c8c0a1f9bde3175f273df044309Sunny Goyalimport java.util.Map;
54290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
55b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyalpublic class FolderPagedView extends PagedView {
56290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
57290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private static final String TAG = "FolderPagedView";
58290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
59b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    private static final boolean ALLOW_FOLDER_SCROLL = true;
60b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal
61290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private static final int REORDER_ANIMATION_DURATION = 230;
624846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    private static final int START_VIEW_REORDER_DELAY = 30;
634846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    private static final float VIEW_REORDER_DELAY_FACTOR = 0.9f;
645d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
653b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    /**
663b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal     * Fraction of the width to scroll when showing the next page hint.
673b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal     */
683b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    private static final float SCROLL_HINT_FRACTION = 0.07f;
693b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
70655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    private static final int[] sTmpArray = new int[2];
71290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
727066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal    public final boolean mIsRtl;
733b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
74290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private final LayoutInflater mInflater;
753333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    private final ViewGroupFocusHelper mFocusIndicatorHelper;
76091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen
77091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final HashMap<View, Runnable> mPendingAnimations = new HashMap<>();
78290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
794ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
80e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxCountX;
814ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
82e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxCountY;
834ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
84e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxItemsPerPage;
85290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
86290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mAllocatedContentSize;
874ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
88290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mGridCountX;
894ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
90290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mGridCountY;
91290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
92290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private Folder mFolder;
93290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private PagedFolderKeyEventListener mKeyListener;
94290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
95c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal    private PageIndicator mPageIndicator;
965d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
97290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public FolderPagedView(Context context, AttributeSet attrs) {
98290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        super(context, attrs);
9987f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal        InvariantDeviceProfile profile = LauncherAppState.getIDP(context);
1002c6e5ccbcd7c3f87e7e85029782440600dc0a3d8Winson Chung        mMaxCountX = profile.numFolderColumns;
1012c6e5ccbcd7c3f87e7e85029782440600dc0a3d8Winson Chung        mMaxCountY = profile.numFolderRows;
102b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal
103290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mMaxItemsPerPage = mMaxCountX * mMaxCountY;
104290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
105290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mInflater = LayoutInflater.from(context);
1063b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
1077066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal        mIsRtl = Utilities.isRtl(getResources());
108db184fdc7bd652e45216a453541ab4a266457a3aSunny Goyal        setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
1094d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal
1101f3f07d47c29cba3b70bcd15ebb65a077f55a558Sunny Goyal        setEdgeGlowColor(Themes.getAttrColor(context, android.R.attr.colorEdgeEffect));
1113333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
112290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
113290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
114290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFolder(Folder folder) {
115290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mFolder = folder;
116290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mKeyListener = new PagedFolderKeyEventListener(folder);
117c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal        mPageIndicator = (PageIndicator) folder.findViewById(R.id.folder_page_indicator);
118d0a6ae7f645e6ba564aebb50316c53fa2e119459Sunny Goyal        initParentViews(folder);
119290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
120290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
121290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
122655ec42ce50e18f2ce597901707057b5898e110aJon Miranda     * Calculates the grid size such that {@param count} items can fit in the grid.
123290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * The grid size is calculated such that countY <= countX and countX = ceil(sqrt(count)) while
124290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * maintaining the restrictions of {@link #mMaxCountX} &amp; {@link #mMaxCountY}.
125290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
126655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    public static void calculateGridSize(int count, int countX, int countY, int maxCountX,
127655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            int maxCountY, int maxItemsPerPage, int[] out) {
128290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        boolean done;
129655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        int gridCountX = countX;
130655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        int gridCountY = countY;
131655ec42ce50e18f2ce597901707057b5898e110aJon Miranda
132655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        if (count >= maxItemsPerPage) {
133655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            gridCountX = maxCountX;
134655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            gridCountY = maxCountY;
135290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            done = true;
136290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
137290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            done = false;
138290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
139290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
140290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (!done) {
141655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            int oldCountX = gridCountX;
142655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            int oldCountY = gridCountY;
143655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            if (gridCountX * gridCountY < count) {
144290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Current grid is too small, expand it
145655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                if ((gridCountX <= gridCountY || gridCountY == maxCountY)
146655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                        && gridCountX < maxCountX) {
147655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                    gridCountX++;
148655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                } else if (gridCountY < maxCountY) {
149655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                    gridCountY++;
150290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
151655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                if (gridCountY == 0) gridCountY++;
152655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            } else if ((gridCountY - 1) * gridCountX >= count && gridCountY >= gridCountX) {
153655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                gridCountY = Math.max(0, gridCountY - 1);
154655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            } else if ((gridCountX - 1) * gridCountY >= count) {
155655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                gridCountX = Math.max(0, gridCountX - 1);
156290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
157655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            done = gridCountX == oldCountX && gridCountY == oldCountY;
158290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
159290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
160655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        out[0] = gridCountX;
161655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        out[1] = gridCountY;
162655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    }
163655ec42ce50e18f2ce597901707057b5898e110aJon Miranda
164655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    /**
165655ec42ce50e18f2ce597901707057b5898e110aJon Miranda     * Sets up the grid size such that {@param count} items can fit in the grid.
166655ec42ce50e18f2ce597901707057b5898e110aJon Miranda     */
167655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    public void setupContentDimensions(int count) {
168655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        mAllocatedContentSize = count;
169655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        calculateGridSize(count, mGridCountX, mGridCountY, mMaxCountX, mMaxCountY, mMaxItemsPerPage,
170655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                sTmpArray);
171655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        mGridCountX = sTmpArray[0];
172655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        mGridCountY = sTmpArray[1];
173655ec42ce50e18f2ce597901707057b5898e110aJon Miranda
174e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        // Update grid size
175e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        for (int i = getPageCount() - 1; i >= 0; i--) {
176290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            getPageAt(i).setGridSize(mGridCountX, mGridCountY);
177290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
178290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
179290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
1803333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    @Override
1813333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    protected void dispatchDraw(Canvas canvas) {
1823333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        mFocusIndicatorHelper.draw(canvas);
1833333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        super.dispatchDraw(canvas);
1843333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    }
1853333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal
186b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
187b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Binds items to the layout.
188b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * @return list of items that could not be bound, probably because we hit the max size limit.
189b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
190290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> items) {
191e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        ArrayList<View> icons = new ArrayList<View>();
192b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        ArrayList<ShortcutInfo> extra = new ArrayList<ShortcutInfo>();
193b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal
194290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (ShortcutInfo item : items) {
195b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal            if (!ALLOW_FOLDER_SCROLL && icons.size() >= mMaxItemsPerPage) {
196b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal                extra.add(item);
197b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal            } else {
198b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal                icons.add(createNewView(item));
199b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal            }
200290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
201e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        arrangeChildren(icons, icons.size(), false);
202b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        return extra;
203290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
204290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
205290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
206290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Create space for a new item at the end, and returns the rank for that item.
207290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Also sets the current page to the last page.
208290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
209e393d3af369c452f3b5f5d9c0a23a83aa3aa736bSunny Goyal    public int allocateRankForNewItem() {
210290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int rank = getItemCount();
2118f288aac99a11d52fd9747f360a8ce3bb521b17aWinson        ArrayList<View> views = new ArrayList<>(mFolder.getItemsInReadingOrder());
2125d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        views.add(rank, null);
2135d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        arrangeChildren(views, views.size(), false);
2145d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        setCurrentPage(rank / mMaxItemsPerPage);
215290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return rank;
216290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
217290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
218290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View createAndAddViewForRank(ShortcutInfo item, int rank) {
219e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        View icon = createNewView(item);
2205d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        addViewForRank(icon, item, rank);
221e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        return icon;
222290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
223290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
224b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
225b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Adds the {@param view} to the layout based on {@param rank} and updated the position
226b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * related attributes. It assumes that {@param item} is already attached to the view.
227b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
228290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void addViewForRank(View view, ShortcutInfo item, int rank) {
229e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        int pagePos = rank % mMaxItemsPerPage;
230e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        int pageNo = rank / mMaxItemsPerPage;
231290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
232290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        item.rank = rank;
233290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        item.cellX = pagePos % mGridCountX;
234290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        item.cellY = pagePos / mGridCountX;
235290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
236e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
237e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        lp.cellX = item.cellX;
238e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        lp.cellY = item.cellY;
239e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        getPageAt(pageNo).addViewToCellLayout(
240e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                view, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true);
241290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
242290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
243e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    @SuppressLint("InflateParams")
244b8c663c492d32963b6ee33750fc985f037c58f10Sunny Goyal    public View createNewView(ShortcutInfo item) {
245290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        final BubbleTextView textView = (BubbleTextView) mInflater.inflate(
246e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                R.layout.folder_application, null, false);
2471cd01b023acc123b771765b7297d8aaedac224e0Sunny Goyal        textView.applyFromShortcutInfo(item);
248290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        textView.setOnClickListener(mFolder);
249290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        textView.setOnLongClickListener(mFolder);
2503333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        textView.setOnFocusChangeListener(mFocusIndicatorHelper);
251290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        textView.setOnKeyListener(mKeyListener);
252290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
253e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        textView.setLayoutParams(new CellLayout.LayoutParams(
254e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                item.cellX, item.cellY, item.spanX, item.spanY));
255290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return textView;
256290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
257290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
258290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
259290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public CellLayout getPageAt(int index) {
260290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return (CellLayout) getChildAt(index);
261290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
262290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
263290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public CellLayout getCurrentCellLayout() {
264290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return getPageAt(getNextPage());
265290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
266290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
267e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private CellLayout createAndAddNewPage() {
2682fd020860533e18c64a93d14d11cb2d34bc9cbafTony        DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
269c13403c612748bfdf06436510600230c4c4b55ecSunny Goyal        CellLayout page = (CellLayout) mInflater.inflate(R.layout.folder_page, this, false);
270e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
271e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
272e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setInvertIfRtl(true);
273e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setGridSize(mGridCountX, mGridCountY);
274290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
27522fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        addView(page, -1, generateDefaultLayoutParams());
276e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        return page;
277290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
278290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
279a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    @Override
280a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    protected int getChildGap() {
281a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal        return getPaddingLeft() + getPaddingRight();
282a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    }
283a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal
284290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFixedSize(int width, int height) {
28522fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        width -= (getPaddingLeft() + getPaddingRight());
28622fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        height -= (getPaddingTop() + getPaddingBottom());
287290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = getChildCount() - 1; i >= 0; i --) {
288290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            ((CellLayout) getChildAt(i)).setFixedSize(width, height);
289290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
290290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
291290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
292290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void removeItem(View v) {
293290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = getChildCount() - 1; i >= 0; i --) {
294290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            getPageAt(i).removeView(v);
295290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
296290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
297290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
298c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal    @Override
299c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
300c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal        super.onScrollChanged(l, t, oldl, oldt);
301c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal        mPageIndicator.setScroll(l, mMaxScrollX);
302c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal    }
303c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal
304290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
305290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Updates position and rank of all the children in the view.
306290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * It essentially removes all views from all the pages and then adds them again in appropriate
307290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * page.
308290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     *
309290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * @param list the ordered list of children.
310290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * @param itemCount if greater than the total children count, empty spaces are left
311290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * at the end, otherwise it is ignored.
312290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     *
313290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
314290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void arrangeChildren(ArrayList<View> list, int itemCount) {
315e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        arrangeChildren(list, itemCount, true);
316e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    }
317e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal
318a07c2f5c80908e8a612f4681314a7068b92baa9fSunny Goyal    @SuppressLint("RtlHardcoded")
319e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private void arrangeChildren(ArrayList<View> list, int itemCount, boolean saveChanges) {
320290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        ArrayList<CellLayout> pages = new ArrayList<CellLayout>();
321290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = 0; i < getChildCount(); i++) {
322290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            CellLayout page = (CellLayout) getChildAt(i);
323290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            page.removeAllViews();
324290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            pages.add(page);
325290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
326290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        setupContentDimensions(itemCount);
327290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
328290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        Iterator<CellLayout> pageItr = pages.iterator();
329290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout currentPage = null;
330290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
331290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int position = 0;
332290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int newX, newY, rank;
333290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
334290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        rank = 0;
3354846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        for (int i = 0; i < itemCount; i++) {
3364846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            View v = list.size() > i ? list.get(i) : null;
337290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (currentPage == null || position >= mMaxItemsPerPage) {
338290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Next page
339290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                if (pageItr.hasNext()) {
340290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    currentPage = pageItr.next();
341290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                } else {
342e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                    currentPage = createAndAddNewPage();
343290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
344290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                position = 0;
345290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
346290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
3474846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            if (v != null) {
3484846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
3494846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                newX = position % mGridCountX;
3504846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                newY = position / mGridCountX;
3514846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                ItemInfo info = (ItemInfo) v.getTag();
3524846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                if (info.cellX != newX || info.cellY != newY || info.rank != rank) {
3534846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.cellX = newX;
3544846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.cellY = newY;
3554846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.rank = rank;
3564846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    if (saveChanges) {
35743bf11d9c95f76c2dfeb625b23cb458df81252b3Sunny Goyal                        mFolder.mLauncher.getModelWriter().addOrMoveItemInDatabase(info,
3584846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                                mFolder.mInfo.id, 0, info.cellX, info.cellY);
3594846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    }
360e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                }
3614846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                lp.cellX = info.cellX;
3624846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                lp.cellY = info.cellY;
3634846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                currentPage.addViewToCellLayout(
3644846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                        v, -1, mFolder.mLauncher.getViewIdForItem(info), lp, true);
365317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal
366317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                if (rank < FolderIcon.NUM_ITEMS_IN_PREVIEW && v instanceof BubbleTextView) {
367317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    ((BubbleTextView) v).verifyHighRes();
368317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                }
369290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
3704846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
371290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            rank ++;
372290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            position++;
373290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
374290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
375e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        // Remove extra views.
376290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        boolean removed = false;
377290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (pageItr.hasNext()) {
378e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal            removeView(pageItr.next());
379e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal            removed = true;
380290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
381290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (removed) {
382290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            setCurrentPage(0);
383290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
3845d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
385b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        setEnableOverscroll(getPageCount() > 1);
3865d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
3875d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        // Update footer
388c487bd34ace268dd8be5480ba884baed6096f76eSunny Goyal        mPageIndicator.setVisibility(getPageCount() > 1 ? View.VISIBLE : View.GONE);
389a07c2f5c80908e8a612f4681314a7068b92baa9fSunny Goyal        // Set the gravity as LEFT or RIGHT instead of START, as START depends on the actual text.
390a07c2f5c80908e8a612f4681314a7068b92baa9fSunny Goyal        mFolder.mFolderName.setGravity(getPageCount() > 1 ?
391a07c2f5c80908e8a612f4681314a7068b92baa9fSunny Goyal                (mIsRtl ? Gravity.RIGHT : Gravity.LEFT) : Gravity.CENTER_HORIZONTAL);
392290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
393290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
394290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getDesiredWidth() {
39522fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        return getPageCount() > 0 ?
39622fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal                (getPageAt(0).getDesiredWidth() + getPaddingLeft() + getPaddingRight()) : 0;
397290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
398290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
399290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getDesiredHeight()  {
40022fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        return  getPageCount() > 0 ?
40122fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal                (getPageAt(0).getDesiredHeight() + getPaddingTop() + getPaddingBottom()) : 0;
402290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
403290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
404290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getItemCount() {
405e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        int lastPageIndex = getChildCount() - 1;
406e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        if (lastPageIndex < 0) {
407e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal            // If there are no pages, nothing has yet been added to the folder.
408e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal            return 0;
4094846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
410e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        return getPageAt(lastPageIndex).getShortcutsAndWidgets().getChildCount()
411e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal                + lastPageIndex * mMaxItemsPerPage;
412290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
413290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
414b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
415b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * @return the rank of the cell nearest to the provided pixel position.
416b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
417290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int findNearestArea(int pixelX, int pixelY) {
418290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageIndex = getNextPage();
419290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout page = getPageAt(pageIndex);
420655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        page.findNearestArea(pixelX, pixelY, 1, 1, sTmpArray);
421290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mFolder.isLayoutRtl()) {
422655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            sTmpArray[0] = page.getCountX() - sTmpArray[0] - 1;
423290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
424290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return Math.min(mAllocatedContentSize - 1,
425655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                pageIndex * mMaxItemsPerPage + sTmpArray[1] * mGridCountX + sTmpArray[0]);
426290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
427290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
428290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public boolean isFull() {
429b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        return !ALLOW_FOLDER_SCROLL && getItemCount() >= mMaxItemsPerPage;
430290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
431290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
432feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham    public View getFirstItem() {
433feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        if (getChildCount() < 1) {
434feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return null;
435feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        }
436feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        ShortcutAndWidgetContainer currContainer = getCurrentCellLayout().getShortcutsAndWidgets();
437feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        if (mGridCountX > 0) {
438feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return currContainer.getChildAt(0, 0);
439feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        } else {
440feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return currContainer.getChildAt(0);
441feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        }
442feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham    }
443feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham
444290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View getLastItem() {
445290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (getChildCount() < 1) {
446290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return null;
447290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
448feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        ShortcutAndWidgetContainer currContainer = getCurrentCellLayout().getShortcutsAndWidgets();
449feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        int lastRank = currContainer.getChildCount() - 1;
450290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mGridCountX > 0) {
451feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return currContainer.getChildAt(lastRank % mGridCountX, lastRank / mGridCountX);
452290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
453feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return currContainer.getChildAt(lastRank);
454290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
455290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
456290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
457b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
458b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Iterates over all its items in a reading order.
459b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * @return the view for which the operator returned true.
460b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
461290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View iterateOverItems(ItemOperator op) {
462290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int k = 0 ; k < getChildCount(); k++) {
463290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            CellLayout page = getPageAt(k);
464290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            for (int j = 0; j < page.getCountY(); j++) {
465290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                for (int i = 0; i < page.getCountX(); i++) {
466290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    View v = page.getChildAt(i, j);
467c52ba710053e4c6927937dd1a26d1abe06b6fa99Sunny Goyal                    if ((v != null) && op.evaluate((ItemInfo) v.getTag(), v)) {
468290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        return v;
469290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    }
470290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
471290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
472290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
473290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return null;
474290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
475290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
476290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public String getAccessibilityDescription() {
477f4f89ef608245d39bbddda05f291361d2ae06667Sunny Goyal        return getContext().getString(R.string.folder_opened, mGridCountX, mGridCountY);
478290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
479290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
480b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
481b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Sets the focus on the first visible child.
482b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
483290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFocusOnFirstChild() {
484290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        View firstChild = getCurrentCellLayout().getChildAt(0, 0);
485290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (firstChild != null) {
486290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            firstChild.requestFocus();
487290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
488290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
489290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
490290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
491290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    protected void notifyPageSwitchListener() {
492290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        super.notifyPageSwitchListener();
493290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mFolder != null) {
494290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            mFolder.updateTextViewFocus();
495290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
496290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
497290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
4984846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    /**
4994846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     * Scrolls the current view by a fraction
5004846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     */
5013b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    public void showScrollHint(int direction) {
502f5440cbd6c0525769d24b890e16313a728831e04Sunny Goyal        float fraction = (direction == Folder.SCROLL_LEFT) ^ mIsRtl
5033b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal                ? -SCROLL_HINT_FRACTION : SCROLL_HINT_FRACTION;
5044846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int hint = (int) (fraction * getWidth());
5054846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int scroll = getScrollForPage(getNextPage()) + hint;
5064d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal        int delta = scroll - getScrollX();
5074846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        if (delta != 0) {
5084846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            mScroller.setInterpolator(new DecelerateInterpolator());
5094d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal            mScroller.startScroll(getScrollX(), 0, delta, 0, Folder.SCROLL_HINT_DURATION);
5104846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            invalidate();
5114846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
5124846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
5134846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
5144846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public void clearScrollHint() {
5154d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal        if (getScrollX() != getScrollForPage(getNextPage())) {
5164846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            snapToPage(getNextPage());
5174846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
5184846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
5194846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
5204846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    /**
5214846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     * Finish animation all the views which are animating across pages
5224846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     */
5234846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public void completePendingPageChanges() {
5245d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        if (!mPendingAnimations.isEmpty()) {
5255d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal            HashMap<View, Runnable> pendingViews = new HashMap<>(mPendingAnimations);
5264846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            for (Map.Entry<View, Runnable> e : pendingViews.entrySet()) {
5274846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                e.getKey().animate().cancel();
5284846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                e.getValue().run();
5294846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            }
5304846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
5314846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
5324846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
5334846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public boolean rankOnCurrentPage(int rank) {
5344846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int p = rank / mMaxItemsPerPage;
5354846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        return p == getNextPage();
5364846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
5374846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
538290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
5399ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal    protected void onPageBeginTransition() {
5409ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal        super.onPageBeginTransition();
5419ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal        // Ensure that adjacent pages have high resolution icons
5429ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal        verifyVisibleHighResIcons(getCurrentPage() - 1);
5439ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal        verifyVisibleHighResIcons(getCurrentPage() + 1);
54434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
54534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
54634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    /**
54734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     * Ensures that all the icons on the given page are of high-res
54834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     */
54934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    public void verifyVisibleHighResIcons(int pageNo) {
55034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        CellLayout page = getPageAt(pageNo);
55134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        if (page != null) {
55234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            ShortcutAndWidgetContainer parent = page.getShortcutsAndWidgets();
55334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            for (int i = parent.getChildCount() - 1; i >= 0; i--) {
55434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                ((BubbleTextView) parent.getChildAt(i)).verifyHighRes();
55534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            }
55634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        }
55734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
55834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
559ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    public int getAllocatedContentSize() {
560ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal        return mAllocatedContentSize;
561ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
562ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
563b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
564b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Reorders the items such that the {@param empty} spot moves to {@param target}
565b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
566290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void realTimeReorder(int empty, int target) {
5674846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        completePendingPageChanges();
568290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int delay = 0;
5694846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        float delayAmount = START_VIEW_REORDER_DELAY;
570290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
571290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        // Animation only happens on the current page.
572290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageToAnimate = getNextPage();
573290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
574290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageT = target / mMaxItemsPerPage;
575290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pagePosT = target % mMaxItemsPerPage;
576290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
577290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (pageT != pageToAnimate) {
578290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            Log.e(TAG, "Cannot animate when the target cell is invisible");
579290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
580290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pagePosE = empty % mMaxItemsPerPage;
581290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageE = empty / mMaxItemsPerPage;
582290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
583290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int startPos, endPos;
584290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int moveStart, moveEnd;
585290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int direction;
586290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
587290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (target == empty) {
588290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // No animation
589290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return;
590290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else if (target > empty) {
591290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // Items will move backwards to make room for the empty cell.
592290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            direction = 1;
593290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
594290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // If empty cell is in a different page, move them instantly.
595290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (pageE < pageToAnimate) {
596290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = empty;
597290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Instantly move the first item in the current page.
598290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveEnd = pageToAnimate * mMaxItemsPerPage;
599290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Animate the 2nd item in the current page, as the first item was already moved to
600290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // the last page.
601290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = 0;
602290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            } else {
603290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = moveEnd = -1;
604290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = pagePosE;
605290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
606290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
607290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            endPos = pagePosT;
608290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
609290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // The items will move forward.
610290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            direction = -1;
611290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
612290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (pageE > pageToAnimate) {
613290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Move the items immediately.
614290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = empty;
615290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Instantly move the last item in the current page.
616290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveEnd = (pageToAnimate + 1) * mMaxItemsPerPage - 1;
617290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
618290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Animations start with the second last item in the page
619290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = mMaxItemsPerPage - 1;
620290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            } else {
621290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = moveEnd = -1;
622290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = pagePosE;
623290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
624290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
625290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            endPos = pagePosT;
626290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
627290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
628290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        // Instant moving views.
629290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (moveStart != moveEnd) {
630290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int rankToMove = moveStart + direction;
631290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int p = rankToMove / mMaxItemsPerPage;
632290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int pagePos = rankToMove % mMaxItemsPerPage;
633290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int x = pagePos % mGridCountX;
634290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int y = pagePos / mGridCountX;
635290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
636290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            final CellLayout page = getPageAt(p);
637290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            final View v = page.getChildAt(x, y);
638290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (v != null) {
639290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                if (pageToAnimate != p) {
640290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    page.removeView(v);
641290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    addViewForRank(v, (ShortcutInfo) v.getTag(), moveStart);
642290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                } else {
643290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    // Do a fake animation before removing it.
644290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    final int newRank = moveStart;
645290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    final float oldTranslateX = v.getTranslationX();
646290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
647290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    Runnable endAction = new Runnable() {
648290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
649290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        @Override
650290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        public void run() {
6515d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                            mPendingAnimations.remove(v);
652290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                            v.setTranslationX(oldTranslateX);
653290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                            ((CellLayout) v.getParent().getParent()).removeView(v);
654290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                            addViewForRank(v, (ShortcutInfo) v.getTag(), newRank);
655290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        }
656290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    };
657290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    v.animate()
6587066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal                        .translationXBy((direction > 0 ^ mIsRtl) ? -v.getWidth() : v.getWidth())
659290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        .setDuration(REORDER_ANIMATION_DURATION)
660290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        .setStartDelay(0)
661290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        .withEndAction(endAction);
6625d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                    mPendingAnimations.put(v, endAction);
663290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
664290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
665290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            moveStart = rankToMove;
666290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
667290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
668290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if ((endPos - startPos) * direction <= 0) {
669290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // No animation
670290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return;
671290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
672290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
673290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout page = getPageAt(pageToAnimate);
674290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = startPos; i != endPos; i += direction) {
675290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int nextPos = i + direction;
676290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            View v = page.getChildAt(nextPos % mGridCountX, nextPos / mGridCountX);
677290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (v != null) {
678290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                ((ItemInfo) v.getTag()).rank -= direction;
679290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
680290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (page.animateChildToPosition(v, i % mGridCountX, i / mGridCountX,
681290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    REORDER_ANIMATION_DURATION, delay, true, true)) {
682290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                delay += delayAmount;
6834846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                delayAmount *= VIEW_REORDER_DELAY_FACTOR;
684290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
685290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
686290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
687b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal
688b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    public int itemsPerPage() {
689b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        return mMaxItemsPerPage;
690b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    }
6914d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal
6924d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal    @Override
6930de011705b132eacdd10f7bfb5cdc4bd79a147e8Hyunyoung Song    protected void getEdgeVerticalPosition(int[] pos) {
6944d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal        pos[0] = 0;
6954d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal        pos[1] = getViewportHeight();
6964d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal    }
697290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal}
698