SingleRow.java revision 134b0891c25facf14c53ef939846010284025ca9
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package android.support.v17.leanback.widget;
15
16import android.support.annotation.NonNull;
17import android.support.v4.util.CircularIntArray;
18import android.support.v7.widget.RecyclerView;
19
20import java.io.PrintWriter;
21
22/**
23 * A Grid with restriction to single row.
24 */
25class SingleRow extends Grid {
26
27    private final Location mTmpLocation = new Location(0);
28    private Object[] mTmpItem = new Object[1];
29
30    SingleRow() {
31        setNumRows(1);
32    }
33
34    @Override
35    public final Location getLocation(int index) {
36        // all items are on row 0, share the same Location object.
37        return mTmpLocation;
38    }
39
40    @Override
41    public final void debugPrint(PrintWriter pw) {
42        pw.print("SingleRow<");
43        pw.print(mFirstVisibleIndex);
44        pw.print(",");
45        pw.print(mLastVisibleIndex);
46        pw.print(">");
47        pw.println();
48    }
49
50    int getStartIndexForAppend() {
51        if (mLastVisibleIndex >= 0) {
52            return mLastVisibleIndex + 1;
53        } else if (mStartIndex != START_DEFAULT) {
54            return Math.min(mStartIndex, mProvider.getCount() - 1);
55        } else {
56            return 0;
57        }
58    }
59
60    int getStartIndexForPrepend() {
61        if (mFirstVisibleIndex >= 0) {
62            return mFirstVisibleIndex - 1;
63        } else if (mStartIndex != START_DEFAULT) {
64            return Math.min(mStartIndex, mProvider.getCount() - 1);
65        } else {
66            return mProvider.getCount() - 1;
67        }
68    }
69
70    @Override
71    protected final boolean prependVisibleItems(int toLimit, boolean oneColumnMode) {
72        if (mProvider.getCount() == 0) {
73            return false;
74        }
75        if (!oneColumnMode && checkPrependOverLimit(toLimit)) {
76            return false;
77        }
78        boolean filledOne = false;
79        int minIndex = mProvider.getMinIndex();
80        for (int index = getStartIndexForPrepend(); index >= minIndex; index--) {
81            int size = mProvider.createItem(index, false, mTmpItem);
82            int edge;
83            if (mFirstVisibleIndex < 0 || mLastVisibleIndex < 0) {
84                edge = mReversedFlow ? Integer.MIN_VALUE : Integer.MAX_VALUE;
85                mLastVisibleIndex = mFirstVisibleIndex = index;
86            } else {
87                if (mReversedFlow) {
88                    edge = mProvider.getEdge(index + 1) + mSpacing + size;
89                } else {
90                    edge = mProvider.getEdge(index + 1) - mSpacing - size;
91                }
92                mFirstVisibleIndex = index;
93            }
94            mProvider.addItem(mTmpItem[0], index, size, 0, edge);
95            filledOne = true;
96            if (oneColumnMode || checkPrependOverLimit(toLimit)) {
97                break;
98            }
99        }
100        return filledOne;
101    }
102
103    @Override
104    protected final boolean appendVisibleItems(int toLimit, boolean oneColumnMode) {
105        if (mProvider.getCount() == 0) {
106            return false;
107        }
108        if (!oneColumnMode && checkAppendOverLimit(toLimit)) {
109            // not in one column mode, return immediately if over limit
110            return false;
111        }
112        boolean filledOne = false;
113        for (int index = getStartIndexForAppend(); index < mProvider.getCount(); index++) {
114            int size = mProvider.createItem(index, true, mTmpItem);
115            int edge;
116            if (mFirstVisibleIndex < 0 || mLastVisibleIndex< 0) {
117                edge = mReversedFlow ? Integer.MAX_VALUE : Integer.MIN_VALUE;
118                mLastVisibleIndex = mFirstVisibleIndex = index;
119            } else {
120                if (mReversedFlow) {
121                    edge = mProvider.getEdge(index - 1) - mProvider.getSize(index - 1) - mSpacing;
122                } else {
123                    edge = mProvider.getEdge(index - 1) + mProvider.getSize(index - 1) + mSpacing;
124                }
125                mLastVisibleIndex = index;
126            }
127            mProvider.addItem(mTmpItem[0], index, size, 0, edge);
128            filledOne = true;
129            if (oneColumnMode || checkAppendOverLimit(toLimit)) {
130                break;
131            }
132        }
133        return filledOne;
134    }
135
136    @Override
137    public void collectAdjacentPrefetchPositions(int fromLimit, int da,
138        @NonNull RecyclerView.LayoutManager.LayoutPrefetchRegistry layoutPrefetchRegistry) {
139        int indexToPrefetch;
140        int nearestEdge;
141        if (mReversedFlow ? da > 0 : da < 0) {
142            // prefetch next prepend, lower index number
143            if (getFirstVisibleIndex() == 0) {
144                return; // no remaining items to prefetch
145            }
146
147            indexToPrefetch = getStartIndexForPrepend();
148            nearestEdge = mProvider.getEdge(mFirstVisibleIndex)
149                    + (mReversedFlow ? mSpacing : -mSpacing);
150        } else {
151            // prefetch next append, higher index number
152            if (getLastVisibleIndex() == mProvider.getCount() - 1) {
153                return; // no remaining items to prefetch
154            }
155
156            indexToPrefetch = getStartIndexForAppend();
157            int itemSizeWithSpace = mProvider.getSize(mLastVisibleIndex) + mSpacing;
158            nearestEdge = mProvider.getEdge(mLastVisibleIndex)
159                    + (mReversedFlow ? -itemSizeWithSpace : itemSizeWithSpace);
160        }
161
162        int distance = Math.abs(nearestEdge - fromLimit);
163        layoutPrefetchRegistry.addPosition(indexToPrefetch, distance);
164    }
165
166    @Override
167    public final CircularIntArray[] getItemPositionsInRows(int startPos, int endPos) {
168        // all items are on the same row:
169        mTmpItemPositionsInRows[0].clear();
170        mTmpItemPositionsInRows[0].addLast(startPos);
171        mTmpItemPositionsInRows[0].addLast(endPos);
172        return mTmpItemPositionsInRows;
173    }
174
175    @Override
176    protected final int findRowMin(boolean findLarge, int indexLimit, int[] indices) {
177        if (indices != null) {
178            indices[0] = 0;
179            indices[1] = indexLimit;
180        }
181        return mReversedFlow ? mProvider.getEdge(indexLimit) - mProvider.getSize(indexLimit)
182                : mProvider.getEdge(indexLimit);
183    }
184
185    @Override
186    protected final int findRowMax(boolean findLarge, int indexLimit, int[] indices) {
187        if (indices != null) {
188            indices[0] = 0;
189            indices[1] = indexLimit;
190        }
191        return mReversedFlow ? mProvider.getEdge(indexLimit)
192                : mProvider.getEdge(indexLimit) + mProvider.getSize(indexLimit);
193    }
194
195}
196