16e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu/* 26e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Copyright (C) 2014 The Android Open Source Project 36e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 46e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 56e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * in compliance with the License. You may obtain a copy of the License at 66e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 76e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * http://www.apache.org/licenses/LICENSE-2.0 86e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 96e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License 106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 116e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * or implied. See the License for the specific language governing permissions and limitations under 126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * the License. 136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gupackage android.support.v17.leanback.widget; 156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 16cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craikimport android.support.annotation.NonNull; 17cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craikimport android.support.annotation.Nullable; 186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Guimport android.support.v4.util.CircularIntArray; 19cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craikimport android.support.v7.widget.RecyclerView; 20c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Guimport android.util.SparseIntArray; 216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 226e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Guimport java.io.PrintWriter; 23c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Guimport java.util.Arrays; 246e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu/** 26f923d595ace34894c49d1609d3c629336b175b89Dake Gu * A grid is representation of single or multiple rows layout data structure and algorithm. 27f923d595ace34894c49d1609d3c629336b175b89Dake Gu * Grid is the base class for single row, non-staggered grid and staggered grid. 286e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * <p> 296e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * To use the Grid, user must implement a Provider to create or remove visible item. 306e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Grid maintains a list of visible items. Visible items are created when 316e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * user calls appendVisibleItems() or prependVisibleItems() with certain limitation 326e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * (e.g. a max edge that append up to). Visible items are deleted when user calls 336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * removeInvisibleItemsAtEnd() or removeInvisibleItemsAtFront(). Grid's algorithm 346e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * uses size of visible item returned from Provider.createItem() to decide which row 356e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * to add a new visible item and may cache the algorithm results. User must call 366e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * invalidateItemsAfter() when it detects item size changed to ask Grid to remove cached 376e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * results. 386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Guabstract class Grid { 406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 416e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * A constant representing a default starting index, indicating that the 436e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * developer did not provide a start index. 446e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 456e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public static final int START_DEFAULT = -1; 466e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 47c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu Object[] mTmpItem = new Object[1]; 48c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu 496e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 506e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * When user uses Grid, he should provide count of items and 516e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * the method to create item and remove item. 526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public static interface Provider { 546e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 556e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 566e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Return how many items (are in the adapter). 576e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 58134b0891c25facf14c53ef939846010284025ca9Dake Gu int getCount(); 59134b0891c25facf14c53ef939846010284025ca9Dake Gu 60134b0891c25facf14c53ef939846010284025ca9Dake Gu /** 61134b0891c25facf14c53ef939846010284025ca9Dake Gu * @return Min index to prepend, usually it's 0; but in the preLayout case, 62134b0891c25facf14c53ef939846010284025ca9Dake Gu * when grid was showing 5,6,7. Removing 3,4,5 will make the layoutPosition to 63134b0891c25facf14c53ef939846010284025ca9Dake Gu * be 3(deleted),4,5 in prelayout pass; Grid's index is still 5,6,7 in prelayout. 64134b0891c25facf14c53ef939846010284025ca9Dake Gu * When we prepend in prelayout, we can call createItem(4), createItem(3), createItem(2), 65134b0891c25facf14c53ef939846010284025ca9Dake Gu * the minimal index is 2, which is also the delta to mapping to layoutPosition in 66134b0891c25facf14c53ef939846010284025ca9Dake Gu * prelayout pass. 67134b0891c25facf14c53ef939846010284025ca9Dake Gu */ 68134b0891c25facf14c53ef939846010284025ca9Dake Gu int getMinIndex(); 696e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 706e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 716e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Create visible item and where the provider should measure it. 726e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * The call is always followed by addItem(). 736e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 746e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param append True if new item is after last visible item, false if new item is 756e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * before first visible item. 766e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param item item[0] returns created item that will be passed in addItem() call. 77c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * @param disappearingItem The item is a disappearing item added by 78c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * {@link Grid#fillDisappearingItems(int[], int, SparseIntArray)}. 79c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * 806e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return length of the item. 816e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 82c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int createItem(int index, boolean append, Object[] item, boolean disappearingItem); 836e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 846e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 856e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * add item to given row and given edge. The call is always after createItem(). 866e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param item The object returned by createItem() 876e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 886e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param length The size of the object 896e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param rowIndex Row index to put the item 906e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param edge min_edge if not reversed or max_edge if reversed. 916e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 92134b0891c25facf14c53ef939846010284025ca9Dake Gu void addItem(Object item, int index, int length, int rowIndex, int edge); 936e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 946e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 956e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Remove visible item at index. 966e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 976e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 98134b0891c25facf14c53ef939846010284025ca9Dake Gu void removeItem(int index); 996e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1006e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1016e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Get edge of an existing visible item. edge will be the min_edge 1026e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * if not reversed or the max_edge if reversed. 1036e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 1046e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 105134b0891c25facf14c53ef939846010284025ca9Dake Gu int getEdge(int index); 1066e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1076e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1086e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Get size of an existing visible item. 1096e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 1106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 111134b0891c25facf14c53ef939846010284025ca9Dake Gu int getSize(int index); 1126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Cached representation of an item in Grid. May be subclassed. 1166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1176e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public static class Location { 1186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1196e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * The index of the row for this Location. 1206e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public int row; 1226e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1236e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public Location(int row) { 1246e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu this.row = row; 1256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1266e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1276e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1286e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected Provider mProvider; 1296e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected boolean mReversedFlow; 130ef4e1b371215f9fffa9245159250740b611dfb4dDake Gu protected int mSpacing; 1316e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mNumRows; 1326e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mFirstVisibleIndex = -1; 1336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mLastVisibleIndex = -1; 1346e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1356e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected CircularIntArray[] mTmpItemPositionsInRows; 1366e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1376e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu // the first index that grid will layout 1386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mStartIndex = START_DEFAULT; 1396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 141f923d595ace34894c49d1609d3c629336b175b89Dake Gu * Creates a single or multiple rows (can be staggered or not staggered) grid 1426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 143f923d595ace34894c49d1609d3c629336b175b89Dake Gu public static Grid createGrid(int rows) { 144f923d595ace34894c49d1609d3c629336b175b89Dake Gu Grid grid; 145f923d595ace34894c49d1609d3c629336b175b89Dake Gu if (rows == 1) { 146f923d595ace34894c49d1609d3c629336b175b89Dake Gu grid = new SingleRow(); 147f923d595ace34894c49d1609d3c629336b175b89Dake Gu } else { 148f923d595ace34894c49d1609d3c629336b175b89Dake Gu // TODO support non staggered multiple rows grid 149f923d595ace34894c49d1609d3c629336b175b89Dake Gu grid = new StaggeredGridDefault(); 150f923d595ace34894c49d1609d3c629336b175b89Dake Gu grid.setNumRows(rows); 151f923d595ace34894c49d1609d3c629336b175b89Dake Gu } 1526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return grid; 1536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1546e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1556e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 156ef4e1b371215f9fffa9245159250740b611dfb4dDake Gu * Sets the space between items in a row 1576e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 158ef4e1b371215f9fffa9245159250740b611dfb4dDake Gu public final void setSpacing(int spacing) { 159ef4e1b371215f9fffa9245159250740b611dfb4dDake Gu mSpacing = spacing; 1606e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1616e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1626e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1636e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets if reversed flow (rtl) 1646e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1656e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final void setReversedFlow(boolean reversedFlow) { 1666e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mReversedFlow = reversedFlow; 1676e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1686e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1696e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1706e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns true if reversed flow (rtl) 1716e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1726e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public boolean isReversedFlow() { 1736e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return mReversedFlow; 1746e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1756e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1766e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1776e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets the {@link Provider} for this grid. 1786e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 1796e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param provider The provider for this grid. 1806e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1816e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void setProvider(Provider provider) { 1826e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mProvider = provider; 1836e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1846e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1856e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1866e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets the first item index to create when there are no items. 1876e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 1886e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param startIndex the index of the first item 1896e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1906e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void setStart(int startIndex) { 1916e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mStartIndex = startIndex; 1926e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1936e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1946e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1956e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns the number of rows in the grid. 1966e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1976e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public int getNumRows() { 1986e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return mNumRows; 1996e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2006e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2016e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2026e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets number of rows to fill into. For views that represent a 2036e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * horizontal list, this will be the rows of the view. For views that 2046e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * represent a vertical list, this will be the columns. 2056e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 2066e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param numRows numberOfRows 2076e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2086e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu void setNumRows(int numRows) { 2096e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (numRows <= 0) { 2106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu throw new IllegalArgumentException(); 2116e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (mNumRows == numRows) { 2136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return; 2146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mNumRows = numRows; 2166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mTmpItemPositionsInRows = new CircularIntArray[mNumRows]; 2176e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu for (int i = 0; i < mNumRows; i++) { 2186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mTmpItemPositionsInRows[i] = new CircularIntArray(); 2196e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2206e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2226e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2236e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns index of first visible item in the staggered grid. Returns negative value 2246e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * if no visible item. 2256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2266e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final int getFirstVisibleIndex() { 2276e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return mFirstVisibleIndex; 2286e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2296e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2306e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2316e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns index of last visible item in the staggered grid. Returns negative value 2326e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * if no visible item. 2336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2346e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final int getLastVisibleIndex() { 2356e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return mLastVisibleIndex; 2366e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2376e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Reset visible indices and keep cache (if exists) 2406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2416e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void resetVisibleIndex() { 2426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mFirstVisibleIndex = mLastVisibleIndex = -1; 2436e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2446e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2456e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2466e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Invalidate items after or equal to index. This will remove visible items 2475723e456309c09c31054d29187fd26b6e2b760efDake Gu * after that and invalidate cache of layout results after that. Note that it's client's 2485723e456309c09c31054d29187fd26b6e2b760efDake Gu * responsibility to perform removing child action, {@link Provider#removeItem(int)} will not 2495723e456309c09c31054d29187fd26b6e2b760efDake Gu * be called because the index might be invalidated. 2506e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2516e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void invalidateItemsAfter(int index) { 2526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (index < 0) { 2536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return; 2546e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2556e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (mLastVisibleIndex < 0) { 2566e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return; 2576e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2585723e456309c09c31054d29187fd26b6e2b760efDake Gu if (mLastVisibleIndex >= index) { 2595723e456309c09c31054d29187fd26b6e2b760efDake Gu mLastVisibleIndex = index - 1; 2606e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 261c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas resetVisibleIndexIfEmpty(); 2626e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (getFirstVisibleIndex() < 0) { 2636e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu setStart(index); 2646e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2656e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2666e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2676e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2686e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Gets the row index of item at given index. 2696e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2706e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final int getRowIndex(int index) { 271e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu Location location = getLocation(index); 272e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu if (location == null) { 273e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu return -1; 274e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu } 275e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu return location.row; 2766e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2776e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2786e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2796e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Gets {@link Location} of item. The return object is read only and temporarily. 2806e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2816e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract Location getLocation(int index); 2826e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2836e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2846e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Finds the largest or smallest row min edge of visible items, 2856e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * the row index is returned in indices[0], the item index is returned in indices[1]. 2866e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 287cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik public final int findRowMin(boolean findLarge, @Nullable int[] indices) { 2886e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return findRowMin(findLarge, mReversedFlow ? mLastVisibleIndex : mFirstVisibleIndex, 2896e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu indices); 2906e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2916e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2926e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2936e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Finds the largest or smallest row min edge of visible items, starts searching from 2946e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * indexLimit, the row index is returned in indices[0], the item index is returned in indices[1]. 2956e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2966e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected abstract int findRowMin(boolean findLarge, int indexLimit, int[] rowIndex); 2976e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2986e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2996e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Finds the largest or smallest row max edge of visible items, the row index is returned in 3006e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * indices[0], the item index is returned in indices[1]. 3016e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 302cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik public final int findRowMax(boolean findLarge, @Nullable int[] indices) { 3036e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return findRowMax(findLarge, mReversedFlow ? mFirstVisibleIndex : mLastVisibleIndex, 3046e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu indices); 3056e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3066e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3076e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3086e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Find largest or smallest row max edge of visible items, starts searching from indexLimit, 3096e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * the row index is returned in indices[0], the item index is returned in indices[1]. 3106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3116e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected abstract int findRowMax(boolean findLarge, int indexLimit, int[] indices); 3126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns true if appending item has reached "toLimit" 3156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected final boolean checkAppendOverLimit(int toLimit) { 31785df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu if (mLastVisibleIndex < 0) { 31885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu return false; 31985df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu } 320ef4e1b371215f9fffa9245159250740b611dfb4dDake Gu return mReversedFlow ? findRowMin(true, null) <= toLimit + mSpacing : 321ef4e1b371215f9fffa9245159250740b611dfb4dDake Gu findRowMax(false, null) >= toLimit - mSpacing; 3226e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3236e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3246e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns true if prepending item has reached "toLimit" 3266e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3276e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected final boolean checkPrependOverLimit(int toLimit) { 32885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu if (mLastVisibleIndex < 0) { 32985df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu return false; 33085df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu } 331ef4e1b371215f9fffa9245159250740b611dfb4dDake Gu return mReversedFlow ? findRowMax(false, null) >= toLimit - mSpacing : 332ef4e1b371215f9fffa9245159250740b611dfb4dDake Gu findRowMin(true, null) <= toLimit + mSpacing; 3336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3346e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3356e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3366e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Return array of int array for all rows, each int array contains visible item positions 3376e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * in pair on that row between startPos(included) and endPositions(included). 3386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returned value is read only, do not change it. 3396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * <p> 3406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * E.g. First row has 3,7,8, second row has 4,5,6. 3416e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * getItemPositionsInRows(3, 8) returns { {3,3,7,8}, {4,6} } 3426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3436e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract CircularIntArray[] getItemPositionsInRows(int startPos, int endPos); 3446e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3456e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3466e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Return array of int array for all rows, each int array contains visible item positions 3476e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * in pair on that row. 3486e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returned value is read only, do not change it. 3496e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * <p> 3506e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * E.g. First row has 3,7,8, second row has 4,5,6 { {3,3,7,8}, {4,6} } 3516e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final CircularIntArray[] getItemPositionsInRows() { 3536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return getItemPositionsInRows(getFirstVisibleIndex(), getLastVisibleIndex()); 3546e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3556e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3566e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3576e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Prepends items and stops after one column is filled. 3586e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * (i.e. filled items from row 0 to row mNumRows - 1) 3596e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return true if at least one item is filled. 3606e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3616e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final boolean prependOneColumnVisibleItems() { 3626e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return prependVisibleItems(mReversedFlow ? Integer.MIN_VALUE : Integer.MAX_VALUE, true); 3636e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3646e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3656e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3666e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Prepends items until first item or reaches toLimit (min edge when not reversed or 3676e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * max edge when reversed) 3686e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3696e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final void prependVisibleItems(int toLimit) { 3706e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu prependVisibleItems(toLimit, false); 3716e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3726e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3736e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3746e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Prepends items until first item or reaches toLimit (min edge when not reversed or 3756e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * max edge when reversed). 3766e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param oneColumnMode true when fills one column and stops, false 3776e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * when checks if condition matches before filling first column. 3786e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return true if at least one item is filled. 3796e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3806e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected abstract boolean prependVisibleItems(int toLimit, boolean oneColumnMode); 3816e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3826e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3836e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Appends items and stops after one column is filled. 3846e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * (i.e. filled items from row 0 to row mNumRows - 1) 3856e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return true if at least one item is filled. 3866e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3876e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public boolean appendOneColumnVisibleItems() { 3886e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return appendVisibleItems(mReversedFlow ? Integer.MAX_VALUE : Integer.MIN_VALUE, true); 3896e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3906e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3916e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3926e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Append items until last item or reaches toLimit (max edge when not 3936e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * reversed or min edge when reversed) 3946e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3956e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final void appendVisibleItems(int toLimit) { 3966e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu appendVisibleItems(toLimit, false); 3976e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3986e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3996e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 4006e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Appends items until last or reaches toLimit (high edge when not 4016e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * reversed or low edge when reversed). 4026e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param oneColumnMode True when fills one column and stops, false 4036e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * when checks if condition matches before filling first column. 4046e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return true if filled at least one item 4056e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 4066e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected abstract boolean appendVisibleItems(int toLimit, boolean oneColumnMode); 4076e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 4086e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 4096e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Removes invisible items from end until reaches item at aboveIndex or toLimit. 410c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * @param aboveIndex Don't remove items whose index is equals or smaller than aboveIndex 411c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * @param toLimit Don't remove items whose left edge is less than toLimit. 4126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 4136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void removeInvisibleItemsAtEnd(int aboveIndex, int toLimit) { 4146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu while(mLastVisibleIndex >= mFirstVisibleIndex && mLastVisibleIndex > aboveIndex) { 4156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu boolean offEnd = !mReversedFlow ? mProvider.getEdge(mLastVisibleIndex) >= toLimit 4166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu : mProvider.getEdge(mLastVisibleIndex) <= toLimit; 4176e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (offEnd) { 4186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mProvider.removeItem(mLastVisibleIndex); 4196e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mLastVisibleIndex--; 4206e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } else { 4216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu break; 4226e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4236e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 424c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas resetVisibleIndexIfEmpty(); 4256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4266e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 4276e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 4286e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Removes invisible items from front until reaches item at belowIndex or toLimit. 429c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * @param belowIndex Don't remove items whose index is equals or larger than belowIndex 430c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * @param toLimit Don't remove items whose right edge is equals or greater than toLimit. 4316e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 4326e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void removeInvisibleItemsAtFront(int belowIndex, int toLimit) { 4336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu while(mLastVisibleIndex >= mFirstVisibleIndex && mFirstVisibleIndex < belowIndex) { 434c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu final int size = mProvider.getSize(mFirstVisibleIndex); 435c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu boolean offFront = !mReversedFlow 436c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu ? mProvider.getEdge(mFirstVisibleIndex) + size <= toLimit 437c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu : mProvider.getEdge(mFirstVisibleIndex) - size >= toLimit; 4386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (offFront) { 4396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mProvider.removeItem(mFirstVisibleIndex); 4406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mFirstVisibleIndex++; 4416e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } else { 4426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu break; 4436e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4446e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 445c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas resetVisibleIndexIfEmpty(); 4466e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4476e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 448c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas private void resetVisibleIndexIfEmpty() { 4496e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (mLastVisibleIndex < mFirstVisibleIndex) { 4506e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu resetVisibleIndex(); 4516e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 454cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik /** 455c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * Fill disappearing items, i.e. the items are moved out of window, we need give them final 456c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * location so recyclerview will run a slide out animation. The positions that was greater than 457c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * last visible index will be appended to end, the positions that was smaller than first visible 458c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * index will be prepend to beginning. 459c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * @param positions Sorted list of positions of disappearing items. 460c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu * @param positionToRow Which row we want to put the disappearing item. 461c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu */ 462c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu public void fillDisappearingItems(int[] positions, int positionsLength, 463c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu SparseIntArray positionToRow) { 464c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu final int lastPos = getLastVisibleIndex(); 465c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu final int resultSearchLast = lastPos >= 0 466c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu ? Arrays.binarySearch(positions, 0, positionsLength, lastPos) : 0; 467c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu if (resultSearchLast < 0) { 468c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu // we shouldn't find lastPos in disappearing position list. 469c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int firstDisappearingIndex = -resultSearchLast - 1; 470c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int edge; 471c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu if (mReversedFlow) { 472c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu edge = mProvider.getEdge(lastPos) - mProvider.getSize(lastPos) - mSpacing; 473c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } else { 474c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu edge = mProvider.getEdge(lastPos) + mProvider.getSize(lastPos) + mSpacing; 475c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 476c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu for (int i = firstDisappearingIndex; i < positionsLength; i++) { 477c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int disappearingIndex = positions[i]; 478c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int disappearingRow = positionToRow.get(disappearingIndex); 479c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu if (disappearingRow < 0) { 480c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu disappearingRow = 0; // if not found put in row 0 481c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 482c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int size = mProvider.createItem(disappearingIndex, true, mTmpItem, true); 483c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu mProvider.addItem(mTmpItem[0], disappearingIndex, size, disappearingRow, edge); 484c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu if (mReversedFlow) { 485c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu edge = edge - size - mSpacing; 486c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } else { 487c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu edge = edge + size + mSpacing; 488c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 489c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 490c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 491c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu 492c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu final int firstPos = getFirstVisibleIndex(); 493c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu final int resultSearchFirst = firstPos >= 0 494c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu ? Arrays.binarySearch(positions, 0, positionsLength, firstPos) : 0; 495c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu if (resultSearchFirst < 0) { 496c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu // we shouldn't find firstPos in disappearing position list. 497c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int firstDisappearingIndex = -resultSearchFirst - 2; 498c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int edge; 499c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu if (mReversedFlow) { 500c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu edge = mProvider.getEdge(firstPos); 501c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } else { 502c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu edge = mProvider.getEdge(firstPos); 503c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 504c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu for (int i = firstDisappearingIndex; i >= 0; i--) { 505c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int disappearingIndex = positions[i]; 506c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int disappearingRow = positionToRow.get(disappearingIndex); 507c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu if (disappearingRow < 0) { 508c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu disappearingRow = 0; // if not found put in row 0 509c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 510c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu int size = mProvider.createItem(disappearingIndex, false, mTmpItem, true); 511c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu if (mReversedFlow) { 512c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu edge = edge + mSpacing + size; 513c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } else { 514c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu edge = edge - mSpacing - size; 515c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 516c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu mProvider.addItem(mTmpItem[0], disappearingIndex, size, disappearingRow, edge); 517c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 518c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 519c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu } 520c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu 521c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu /** 522cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik * Queries items adjacent to the viewport (in the direction of da) into the prefetch registry. 523cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik */ 524cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik public void collectAdjacentPrefetchPositions(int fromLimit, int da, 525cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik @NonNull RecyclerView.LayoutManager.LayoutPrefetchRegistry layoutPrefetchRegistry) { 526cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik } 527cf2ed161d09de8af108dfa9775b2d4449d46306aChris Craik 5286e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract void debugPrint(PrintWriter pw); 5296e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu} 530