Home | History | Annotate | Download | only in widget
      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  */
     14 package androidx.leanback.widget;
     15 
     16 import androidx.annotation.NonNull;
     17 import androidx.collection.CircularIntArray;
     18 import androidx.recyclerview.widget.RecyclerView;
     19 
     20 import java.io.PrintWriter;
     21 
     22 /**
     23  * A Grid with restriction to single row.
     24  */
     25 class SingleRow extends Grid {
     26 
     27     private final Location mTmpLocation = new Location(0);
     28 
     29     SingleRow() {
     30         setNumRows(1);
     31     }
     32 
     33     @Override
     34     public final Location getLocation(int index) {
     35         // all items are on row 0, share the same Location object.
     36         return mTmpLocation;
     37     }
     38 
     39     @Override
     40     public final void debugPrint(PrintWriter pw) {
     41         pw.print("SingleRow<");
     42         pw.print(mFirstVisibleIndex);
     43         pw.print(",");
     44         pw.print(mLastVisibleIndex);
     45         pw.print(">");
     46         pw.println();
     47     }
     48 
     49     int getStartIndexForAppend() {
     50         if (mLastVisibleIndex >= 0) {
     51             return mLastVisibleIndex + 1;
     52         } else if (mStartIndex != START_DEFAULT) {
     53             return Math.min(mStartIndex, mProvider.getCount() - 1);
     54         } else {
     55             return 0;
     56         }
     57     }
     58 
     59     int getStartIndexForPrepend() {
     60         if (mFirstVisibleIndex >= 0) {
     61             return mFirstVisibleIndex - 1;
     62         } else if (mStartIndex != START_DEFAULT) {
     63             return Math.min(mStartIndex, mProvider.getCount() - 1);
     64         } else {
     65             return mProvider.getCount() - 1;
     66         }
     67     }
     68 
     69     @Override
     70     protected final boolean prependVisibleItems(int toLimit, boolean oneColumnMode) {
     71         if (mProvider.getCount() == 0) {
     72             return false;
     73         }
     74         if (!oneColumnMode && checkPrependOverLimit(toLimit)) {
     75             return false;
     76         }
     77         boolean filledOne = false;
     78         int minIndex = mProvider.getMinIndex();
     79         for (int index = getStartIndexForPrepend(); index >= minIndex; index--) {
     80             int size = mProvider.createItem(index, false, mTmpItem, false);
     81             int edge;
     82             if (mFirstVisibleIndex < 0 || mLastVisibleIndex < 0) {
     83                 edge = mReversedFlow ? Integer.MIN_VALUE : Integer.MAX_VALUE;
     84                 mLastVisibleIndex = mFirstVisibleIndex = index;
     85             } else {
     86                 if (mReversedFlow) {
     87                     edge = mProvider.getEdge(index + 1) + mSpacing + size;
     88                 } else {
     89                     edge = mProvider.getEdge(index + 1) - mSpacing - size;
     90                 }
     91                 mFirstVisibleIndex = index;
     92             }
     93             mProvider.addItem(mTmpItem[0], index, size, 0, edge);
     94             filledOne = true;
     95             if (oneColumnMode || checkPrependOverLimit(toLimit)) {
     96                 break;
     97             }
     98         }
     99         return filledOne;
    100     }
    101 
    102     @Override
    103     protected final boolean appendVisibleItems(int toLimit, boolean oneColumnMode) {
    104         if (mProvider.getCount() == 0) {
    105             return false;
    106         }
    107         if (!oneColumnMode && checkAppendOverLimit(toLimit)) {
    108             // not in one column mode, return immediately if over limit
    109             return false;
    110         }
    111         boolean filledOne = false;
    112         for (int index = getStartIndexForAppend(); index < mProvider.getCount(); index++) {
    113             int size = mProvider.createItem(index, true, mTmpItem, false);
    114             int edge;
    115             if (mFirstVisibleIndex < 0 || mLastVisibleIndex< 0) {
    116                 edge = mReversedFlow ? Integer.MAX_VALUE : Integer.MIN_VALUE;
    117                 mLastVisibleIndex = mFirstVisibleIndex = index;
    118             } else {
    119                 if (mReversedFlow) {
    120                     edge = mProvider.getEdge(index - 1) - mProvider.getSize(index - 1) - mSpacing;
    121                 } else {
    122                     edge = mProvider.getEdge(index - 1) + mProvider.getSize(index - 1) + mSpacing;
    123                 }
    124                 mLastVisibleIndex = index;
    125             }
    126             mProvider.addItem(mTmpItem[0], index, size, 0, edge);
    127             filledOne = true;
    128             if (oneColumnMode || checkAppendOverLimit(toLimit)) {
    129                 break;
    130             }
    131         }
    132         return filledOne;
    133     }
    134 
    135     @Override
    136     public void collectAdjacentPrefetchPositions(int fromLimit, int da,
    137         @NonNull RecyclerView.LayoutManager.LayoutPrefetchRegistry layoutPrefetchRegistry) {
    138         int indexToPrefetch;
    139         int nearestEdge;
    140         if (mReversedFlow ? da > 0 : da < 0) {
    141             // prefetch next prepend, lower index number
    142             if (getFirstVisibleIndex() == 0) {
    143                 return; // no remaining items to prefetch
    144             }
    145 
    146             indexToPrefetch = getStartIndexForPrepend();
    147             nearestEdge = mProvider.getEdge(mFirstVisibleIndex)
    148                     + (mReversedFlow ? mSpacing : -mSpacing);
    149         } else {
    150             // prefetch next append, higher index number
    151             if (getLastVisibleIndex() == mProvider.getCount() - 1) {
    152                 return; // no remaining items to prefetch
    153             }
    154 
    155             indexToPrefetch = getStartIndexForAppend();
    156             int itemSizeWithSpace = mProvider.getSize(mLastVisibleIndex) + mSpacing;
    157             nearestEdge = mProvider.getEdge(mLastVisibleIndex)
    158                     + (mReversedFlow ? -itemSizeWithSpace : itemSizeWithSpace);
    159         }
    160 
    161         int distance = Math.abs(nearestEdge - fromLimit);
    162         layoutPrefetchRegistry.addPosition(indexToPrefetch, distance);
    163     }
    164 
    165     @Override
    166     public final CircularIntArray[] getItemPositionsInRows(int startPos, int endPos) {
    167         // all items are on the same row:
    168         mTmpItemPositionsInRows[0].clear();
    169         mTmpItemPositionsInRows[0].addLast(startPos);
    170         mTmpItemPositionsInRows[0].addLast(endPos);
    171         return mTmpItemPositionsInRows;
    172     }
    173 
    174     @Override
    175     protected final int findRowMin(boolean findLarge, int indexLimit, int[] indices) {
    176         if (indices != null) {
    177             indices[0] = 0;
    178             indices[1] = indexLimit;
    179         }
    180         return mReversedFlow ? mProvider.getEdge(indexLimit) - mProvider.getSize(indexLimit)
    181                 : mProvider.getEdge(indexLimit);
    182     }
    183 
    184     @Override
    185     protected final int findRowMax(boolean findLarge, int indexLimit, int[] indices) {
    186         if (indices != null) {
    187             indices[0] = 0;
    188             indices[1] = indexLimit;
    189         }
    190         return mReversedFlow ? mProvider.getEdge(indexLimit)
    191                 : mProvider.getEdge(indexLimit) + mProvider.getSize(indexLimit);
    192     }
    193 
    194 }
    195