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