Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2014 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 static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
     17 
     18 import android.content.Context;
     19 import android.content.res.TypedArray;
     20 import android.graphics.Rect;
     21 import android.util.AttributeSet;
     22 import android.view.Gravity;
     23 import android.view.KeyEvent;
     24 import android.view.MotionEvent;
     25 import android.view.View;
     26 
     27 import androidx.annotation.RestrictTo;
     28 import androidx.leanback.R;
     29 import androidx.recyclerview.widget.RecyclerView;
     30 import androidx.recyclerview.widget.SimpleItemAnimator;
     31 
     32 /**
     33  * An abstract base class for vertically and horizontally scrolling lists. The items come
     34  * from the {@link RecyclerView.Adapter} associated with this view.
     35  * Do not directly use this class, use {@link VerticalGridView} and {@link HorizontalGridView}.
     36  * The class is not intended to be subclassed other than {@link VerticalGridView} and
     37  * {@link HorizontalGridView}.
     38  */
     39 public abstract class BaseGridView extends RecyclerView {
     40 
     41     /**
     42      * Always keep focused item at a aligned position.  Developer can use
     43      * WINDOW_ALIGN_XXX and ITEM_ALIGN_XXX to define how focused item is aligned.
     44      * In this mode, the last focused position will be remembered and restored when focus
     45      * is back to the view.
     46      * @hide
     47      */
     48     @RestrictTo(LIBRARY_GROUP)
     49     public final static int FOCUS_SCROLL_ALIGNED = 0;
     50 
     51     /**
     52      * Scroll to make the focused item inside client area.
     53      * @hide
     54      */
     55     @RestrictTo(LIBRARY_GROUP)
     56     public final static int FOCUS_SCROLL_ITEM = 1;
     57 
     58     /**
     59      * Scroll a page of items when focusing to item outside the client area.
     60      * The page size matches the client area size of RecyclerView.
     61      * @hide
     62      */
     63     @RestrictTo(LIBRARY_GROUP)
     64     public final static int FOCUS_SCROLL_PAGE = 2;
     65 
     66     /**
     67      * The first item is aligned with the low edge of the viewport. When
     68      * navigating away from the first item, the focus item is aligned to a key line location.
     69      * <p>
     70      * For HorizontalGridView, low edge refers to getPaddingLeft() when RTL is false or
     71      * getWidth() - getPaddingRight() when RTL is true.
     72      * For VerticalGridView, low edge refers to getPaddingTop().
     73      * <p>
     74      * The key line location is calculated by "windowAlignOffset" and
     75      * "windowAlignOffsetPercent"; if neither of these two is defined, the
     76      * default value is 1/2 of the size.
     77      * <p>
     78      * Note if there are very few items between low edge and key line, use
     79      * {@link #setWindowAlignmentPreferKeyLineOverLowEdge(boolean)} to control whether you prefer
     80      * to align the items to key line or low edge. Default is preferring low edge.
     81      */
     82     public final static int WINDOW_ALIGN_LOW_EDGE = 1;
     83 
     84     /**
     85      * The last item is aligned with the high edge of the viewport when
     86      * navigating to the end of list. When navigating away from the end, the
     87      * focus item is aligned to a key line location.
     88      * <p>
     89      * For HorizontalGridView, high edge refers to getWidth() - getPaddingRight() when RTL is false
     90      * or getPaddingLeft() when RTL is true.
     91      * For VerticalGridView, high edge refers to getHeight() - getPaddingBottom().
     92      * <p>
     93      * The key line location is calculated by "windowAlignOffset" and
     94      * "windowAlignOffsetPercent"; if neither of these two is defined, the
     95      * default value is 1/2 of the size.
     96      * <p>
     97      * Note if there are very few items between high edge and key line, use
     98      * {@link #setWindowAlignmentPreferKeyLineOverHighEdge(boolean)} to control whether you prefer
     99      * to align the items to key line or high edge. Default is preferring key line.
    100      */
    101     public final static int WINDOW_ALIGN_HIGH_EDGE = 1 << 1;
    102 
    103     /**
    104      * The first item and last item are aligned with the two edges of the
    105      * viewport. When navigating in the middle of list, the focus maintains a
    106      * key line location.
    107      * <p>
    108      * The key line location is calculated by "windowAlignOffset" and
    109      * "windowAlignOffsetPercent"; if neither of these two is defined, the
    110      * default value is 1/2 of the size.
    111      */
    112     public final static int WINDOW_ALIGN_BOTH_EDGE =
    113             WINDOW_ALIGN_LOW_EDGE | WINDOW_ALIGN_HIGH_EDGE;
    114 
    115     /**
    116      * The focused item always stays in a key line location.
    117      * <p>
    118      * The key line location is calculated by "windowAlignOffset" and
    119      * "windowAlignOffsetPercent"; if neither of these two is defined, the
    120      * default value is 1/2 of the size.
    121      */
    122     public final static int WINDOW_ALIGN_NO_EDGE = 0;
    123 
    124     /**
    125      * Value indicates that percent is not used.
    126      */
    127     public final static float WINDOW_ALIGN_OFFSET_PERCENT_DISABLED = -1;
    128 
    129     /**
    130      * Value indicates that percent is not used.
    131      */
    132     public final static float ITEM_ALIGN_OFFSET_PERCENT_DISABLED =
    133             ItemAlignmentFacet.ITEM_ALIGN_OFFSET_PERCENT_DISABLED;
    134 
    135     /**
    136      * Dont save states of any child views.
    137      */
    138     public static final int SAVE_NO_CHILD = 0;
    139 
    140     /**
    141      * Only save on screen child views, the states are lost when they become off screen.
    142      */
    143     public static final int SAVE_ON_SCREEN_CHILD = 1;
    144 
    145     /**
    146      * Save on screen views plus save off screen child views states up to
    147      * {@link #getSaveChildrenLimitNumber()}.
    148      */
    149     public static final int SAVE_LIMITED_CHILD = 2;
    150 
    151     /**
    152      * Save on screen views plus save off screen child views without any limitation.
    153      * This might cause out of memory, only use it when you are dealing with limited data.
    154      */
    155     public static final int SAVE_ALL_CHILD = 3;
    156 
    157     /**
    158      * Listener for intercepting touch dispatch events.
    159      */
    160     public interface OnTouchInterceptListener {
    161         /**
    162          * Returns true if the touch dispatch event should be consumed.
    163          */
    164         public boolean onInterceptTouchEvent(MotionEvent event);
    165     }
    166 
    167     /**
    168      * Listener for intercepting generic motion dispatch events.
    169      */
    170     public interface OnMotionInterceptListener {
    171         /**
    172          * Returns true if the touch dispatch event should be consumed.
    173          */
    174         public boolean onInterceptMotionEvent(MotionEvent event);
    175     }
    176 
    177     /**
    178      * Listener for intercepting key dispatch events.
    179      */
    180     public interface OnKeyInterceptListener {
    181         /**
    182          * Returns true if the key dispatch event should be consumed.
    183          */
    184         public boolean onInterceptKeyEvent(KeyEvent event);
    185     }
    186 
    187     public interface OnUnhandledKeyListener {
    188         /**
    189          * Returns true if the key event should be consumed.
    190          */
    191         public boolean onUnhandledKey(KeyEvent event);
    192     }
    193 
    194     final GridLayoutManager mLayoutManager;
    195 
    196     /**
    197      * Animate layout changes from a child resizing or adding/removing a child.
    198      */
    199     private boolean mAnimateChildLayout = true;
    200 
    201     private boolean mHasOverlappingRendering = true;
    202 
    203     private RecyclerView.ItemAnimator mSavedItemAnimator;
    204 
    205     private OnTouchInterceptListener mOnTouchInterceptListener;
    206     private OnMotionInterceptListener mOnMotionInterceptListener;
    207     private OnKeyInterceptListener mOnKeyInterceptListener;
    208     RecyclerView.RecyclerListener mChainedRecyclerListener;
    209     private OnUnhandledKeyListener mOnUnhandledKeyListener;
    210 
    211     /**
    212      * Number of items to prefetch when first coming on screen with new data.
    213      */
    214     int mInitialPrefetchItemCount = 4;
    215 
    216     BaseGridView(Context context, AttributeSet attrs, int defStyle) {
    217         super(context, attrs, defStyle);
    218         mLayoutManager = new GridLayoutManager(this);
    219         setLayoutManager(mLayoutManager);
    220         // leanback LayoutManager already restores focus inside onLayoutChildren().
    221         setPreserveFocusAfterLayout(false);
    222         setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
    223         setHasFixedSize(true);
    224         setChildrenDrawingOrderEnabled(true);
    225         setWillNotDraw(true);
    226         setOverScrollMode(View.OVER_SCROLL_NEVER);
    227         // Disable change animation by default on leanback.
    228         // Change animation will create a new view and cause undesired
    229         // focus animation between the old view and new view.
    230         ((SimpleItemAnimator)getItemAnimator()).setSupportsChangeAnimations(false);
    231         super.setRecyclerListener(new RecyclerView.RecyclerListener() {
    232             @Override
    233             public void onViewRecycled(RecyclerView.ViewHolder holder) {
    234                 mLayoutManager.onChildRecycled(holder);
    235                 if (mChainedRecyclerListener != null) {
    236                     mChainedRecyclerListener.onViewRecycled(holder);
    237                 }
    238             }
    239         });
    240     }
    241 
    242     void initBaseGridViewAttributes(Context context, AttributeSet attrs) {
    243         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.lbBaseGridView);
    244         boolean throughFront = a.getBoolean(R.styleable.lbBaseGridView_focusOutFront, false);
    245         boolean throughEnd = a.getBoolean(R.styleable.lbBaseGridView_focusOutEnd, false);
    246         mLayoutManager.setFocusOutAllowed(throughFront, throughEnd);
    247         boolean throughSideStart = a.getBoolean(R.styleable.lbBaseGridView_focusOutSideStart, true);
    248         boolean throughSideEnd = a.getBoolean(R.styleable.lbBaseGridView_focusOutSideEnd, true);
    249         mLayoutManager.setFocusOutSideAllowed(throughSideStart, throughSideEnd);
    250         mLayoutManager.setVerticalSpacing(
    251                 a.getDimensionPixelSize(R.styleable.lbBaseGridView_android_verticalSpacing,
    252                         a.getDimensionPixelSize(R.styleable.lbBaseGridView_verticalMargin, 0)));
    253         mLayoutManager.setHorizontalSpacing(
    254                 a.getDimensionPixelSize(R.styleable.lbBaseGridView_android_horizontalSpacing,
    255                         a.getDimensionPixelSize(R.styleable.lbBaseGridView_horizontalMargin, 0)));
    256         if (a.hasValue(R.styleable.lbBaseGridView_android_gravity)) {
    257             setGravity(a.getInt(R.styleable.lbBaseGridView_android_gravity, Gravity.NO_GRAVITY));
    258         }
    259         a.recycle();
    260     }
    261 
    262     /**
    263      * Sets the strategy used to scroll in response to item focus changing:
    264      * <ul>
    265      * <li>{@link #FOCUS_SCROLL_ALIGNED} (default) </li>
    266      * <li>{@link #FOCUS_SCROLL_ITEM}</li>
    267      * <li>{@link #FOCUS_SCROLL_PAGE}</li>
    268      * </ul>
    269      * @hide
    270      */
    271     @RestrictTo(LIBRARY_GROUP)
    272     public void setFocusScrollStrategy(int scrollStrategy) {
    273         if (scrollStrategy != FOCUS_SCROLL_ALIGNED && scrollStrategy != FOCUS_SCROLL_ITEM
    274             && scrollStrategy != FOCUS_SCROLL_PAGE) {
    275             throw new IllegalArgumentException("Invalid scrollStrategy");
    276         }
    277         mLayoutManager.setFocusScrollStrategy(scrollStrategy);
    278         requestLayout();
    279     }
    280 
    281     /**
    282      * Returns the strategy used to scroll in response to item focus changing.
    283      * <ul>
    284      * <li>{@link #FOCUS_SCROLL_ALIGNED} (default) </li>
    285      * <li>{@link #FOCUS_SCROLL_ITEM}</li>
    286      * <li>{@link #FOCUS_SCROLL_PAGE}</li>
    287      * </ul>
    288      * @hide
    289      */
    290     @RestrictTo(LIBRARY_GROUP)
    291     public int getFocusScrollStrategy() {
    292         return mLayoutManager.getFocusScrollStrategy();
    293     }
    294 
    295     /**
    296      * Sets the method for focused item alignment in the view.
    297      *
    298      * @param windowAlignment {@link #WINDOW_ALIGN_BOTH_EDGE},
    299      *        {@link #WINDOW_ALIGN_LOW_EDGE}, {@link #WINDOW_ALIGN_HIGH_EDGE} or
    300      *        {@link #WINDOW_ALIGN_NO_EDGE}.
    301      */
    302     public void setWindowAlignment(int windowAlignment) {
    303         mLayoutManager.setWindowAlignment(windowAlignment);
    304         requestLayout();
    305     }
    306 
    307     /**
    308      * Returns the method for focused item alignment in the view.
    309      *
    310      * @return {@link #WINDOW_ALIGN_BOTH_EDGE}, {@link #WINDOW_ALIGN_LOW_EDGE},
    311      *         {@link #WINDOW_ALIGN_HIGH_EDGE} or {@link #WINDOW_ALIGN_NO_EDGE}.
    312      */
    313     public int getWindowAlignment() {
    314         return mLayoutManager.getWindowAlignment();
    315     }
    316 
    317     /**
    318      * Sets whether prefer key line over low edge when {@link #WINDOW_ALIGN_LOW_EDGE} is used.
    319      * When true, if there are very few items between low edge and key line, align items to key
    320      * line instead of align items to low edge.
    321      * Default value is false (aka prefer align to low edge).
    322      *
    323      * @param preferKeyLineOverLowEdge True to prefer key line over low edge, false otherwise.
    324      */
    325     public void setWindowAlignmentPreferKeyLineOverLowEdge(boolean preferKeyLineOverLowEdge) {
    326         mLayoutManager.mWindowAlignment.mainAxis()
    327                 .setPreferKeylineOverLowEdge(preferKeyLineOverLowEdge);
    328         requestLayout();
    329     }
    330 
    331 
    332     /**
    333      * Returns whether prefer key line over high edge when {@link #WINDOW_ALIGN_HIGH_EDGE} is used.
    334      * When true, if there are very few items between high edge and key line, align items to key
    335      * line instead of align items to high edge.
    336      * Default value is true (aka prefer align to key line).
    337      *
    338      * @param preferKeyLineOverHighEdge True to prefer key line over high edge, false otherwise.
    339      */
    340     public void setWindowAlignmentPreferKeyLineOverHighEdge(boolean preferKeyLineOverHighEdge) {
    341         mLayoutManager.mWindowAlignment.mainAxis()
    342                 .setPreferKeylineOverHighEdge(preferKeyLineOverHighEdge);
    343         requestLayout();
    344     }
    345 
    346     /**
    347      * Returns whether prefer key line over low edge when {@link #WINDOW_ALIGN_LOW_EDGE} is used.
    348      * When true, if there are very few items between low edge and key line, align items to key
    349      * line instead of align items to low edge.
    350      * Default value is false (aka prefer align to low edge).
    351      *
    352      * @return True to prefer key line over low edge, false otherwise.
    353      */
    354     public boolean isWindowAlignmentPreferKeyLineOverLowEdge() {
    355         return mLayoutManager.mWindowAlignment.mainAxis().isPreferKeylineOverLowEdge();
    356     }
    357 
    358 
    359     /**
    360      * Returns whether prefer key line over high edge when {@link #WINDOW_ALIGN_HIGH_EDGE} is used.
    361      * When true, if there are very few items between high edge and key line, align items to key
    362      * line instead of align items to high edge.
    363      * Default value is true (aka prefer align to key line).
    364      *
    365      * @return True to prefer key line over high edge, false otherwise.
    366      */
    367     public boolean isWindowAlignmentPreferKeyLineOverHighEdge() {
    368         return mLayoutManager.mWindowAlignment.mainAxis().isPreferKeylineOverHighEdge();
    369     }
    370 
    371 
    372     /**
    373      * Sets the offset in pixels for window alignment key line.
    374      *
    375      * @param offset The number of pixels to offset.  If the offset is positive,
    376      *        it is distance from low edge (see {@link #WINDOW_ALIGN_LOW_EDGE});
    377      *        if the offset is negative, the absolute value is distance from high
    378      *        edge (see {@link #WINDOW_ALIGN_HIGH_EDGE}).
    379      *        Default value is 0.
    380      */
    381     public void setWindowAlignmentOffset(int offset) {
    382         mLayoutManager.setWindowAlignmentOffset(offset);
    383         requestLayout();
    384     }
    385 
    386     /**
    387      * Returns the offset in pixels for window alignment key line.
    388      *
    389      * @return The number of pixels to offset.  If the offset is positive,
    390      *        it is distance from low edge (see {@link #WINDOW_ALIGN_LOW_EDGE});
    391      *        if the offset is negative, the absolute value is distance from high
    392      *        edge (see {@link #WINDOW_ALIGN_HIGH_EDGE}).
    393      *        Default value is 0.
    394      */
    395     public int getWindowAlignmentOffset() {
    396         return mLayoutManager.getWindowAlignmentOffset();
    397     }
    398 
    399     /**
    400      * Sets the offset percent for window alignment key line in addition to {@link
    401      * #getWindowAlignmentOffset()}.
    402      *
    403      * @param offsetPercent Percentage to offset. E.g., 40 means 40% of the
    404      *        width from low edge. Use
    405      *        {@link #WINDOW_ALIGN_OFFSET_PERCENT_DISABLED} to disable.
    406      *         Default value is 50.
    407      */
    408     public void setWindowAlignmentOffsetPercent(float offsetPercent) {
    409         mLayoutManager.setWindowAlignmentOffsetPercent(offsetPercent);
    410         requestLayout();
    411     }
    412 
    413     /**
    414      * Returns the offset percent for window alignment key line in addition to
    415      * {@link #getWindowAlignmentOffset()}.
    416      *
    417      * @return Percentage to offset. E.g., 40 means 40% of the width from the
    418      *         low edge, or {@link #WINDOW_ALIGN_OFFSET_PERCENT_DISABLED} if
    419      *         disabled. Default value is 50.
    420      */
    421     public float getWindowAlignmentOffsetPercent() {
    422         return mLayoutManager.getWindowAlignmentOffsetPercent();
    423     }
    424 
    425     /**
    426      * Sets number of pixels to the end of low edge. Supports right to left layout direction.
    427      * Item alignment settings are ignored for the child if {@link ItemAlignmentFacet}
    428      * is provided by {@link RecyclerView.ViewHolder} or {@link FacetProviderAdapter}.
    429      *
    430      * @param offset In left to right or vertical case, it's the offset added to left/top edge.
    431      *               In right to left case, it's the offset subtracted from right edge.
    432      */
    433     public void setItemAlignmentOffset(int offset) {
    434         mLayoutManager.setItemAlignmentOffset(offset);
    435         requestLayout();
    436     }
    437 
    438     /**
    439      * Returns number of pixels to the end of low edge. Supports right to left layout direction. In
    440      * left to right or vertical case, it's the offset added to left/top edge. In right to left
    441      * case, it's the offset subtracted from right edge.
    442      * Item alignment settings are ignored for the child if {@link ItemAlignmentFacet}
    443      * is provided by {@link RecyclerView.ViewHolder} or {@link FacetProviderAdapter}.
    444      *
    445      * @return The number of pixels to the end of low edge.
    446      */
    447     public int getItemAlignmentOffset() {
    448         return mLayoutManager.getItemAlignmentOffset();
    449     }
    450 
    451     /**
    452      * Sets whether applies padding to item alignment when {@link #getItemAlignmentOffsetPercent()}
    453      * is 0 or 100.
    454      * <p>When true:
    455      * Applies start/top padding if {@link #getItemAlignmentOffsetPercent()} is 0.
    456      * Applies end/bottom padding if {@link #getItemAlignmentOffsetPercent()} is 100.
    457      * Does not apply padding if {@link #getItemAlignmentOffsetPercent()} is neither 0 nor 100.
    458      * </p>
    459      * <p>When false: does not apply padding</p>
    460      */
    461     public void setItemAlignmentOffsetWithPadding(boolean withPadding) {
    462         mLayoutManager.setItemAlignmentOffsetWithPadding(withPadding);
    463         requestLayout();
    464     }
    465 
    466     /**
    467      * Returns true if applies padding to item alignment when
    468      * {@link #getItemAlignmentOffsetPercent()} is 0 or 100; returns false otherwise.
    469      * <p>When true:
    470      * Applies start/top padding when {@link #getItemAlignmentOffsetPercent()} is 0.
    471      * Applies end/bottom padding when {@link #getItemAlignmentOffsetPercent()} is 100.
    472      * Does not apply padding if {@link #getItemAlignmentOffsetPercent()} is neither 0 nor 100.
    473      * </p>
    474      * <p>When false: does not apply padding</p>
    475      */
    476     public boolean isItemAlignmentOffsetWithPadding() {
    477         return mLayoutManager.isItemAlignmentOffsetWithPadding();
    478     }
    479 
    480     /**
    481      * Sets the offset percent for item alignment in addition to {@link
    482      * #getItemAlignmentOffset()}.
    483      * Item alignment settings are ignored for the child if {@link ItemAlignmentFacet}
    484      * is provided by {@link RecyclerView.ViewHolder} or {@link FacetProviderAdapter}.
    485      *
    486      * @param offsetPercent Percentage to offset. E.g., 40 means 40% of the
    487      *        width from the low edge. Use
    488      *        {@link #ITEM_ALIGN_OFFSET_PERCENT_DISABLED} to disable.
    489      */
    490     public void setItemAlignmentOffsetPercent(float offsetPercent) {
    491         mLayoutManager.setItemAlignmentOffsetPercent(offsetPercent);
    492         requestLayout();
    493     }
    494 
    495     /**
    496      * Returns the offset percent for item alignment in addition to {@link
    497      * #getItemAlignmentOffset()}.
    498      *
    499      * @return Percentage to offset. E.g., 40 means 40% of the width from the
    500      *         low edge, or {@link #ITEM_ALIGN_OFFSET_PERCENT_DISABLED} if
    501      *         disabled. Default value is 50.
    502      */
    503     public float getItemAlignmentOffsetPercent() {
    504         return mLayoutManager.getItemAlignmentOffsetPercent();
    505     }
    506 
    507     /**
    508      * Sets the id of the view to align with. Use {@link android.view.View#NO_ID} (default)
    509      * for the root {@link RecyclerView.ViewHolder#itemView}.
    510      * Item alignment settings on BaseGridView are if {@link ItemAlignmentFacet}
    511      * is provided by {@link RecyclerView.ViewHolder} or {@link FacetProviderAdapter}.
    512      */
    513     public void setItemAlignmentViewId(int viewId) {
    514         mLayoutManager.setItemAlignmentViewId(viewId);
    515     }
    516 
    517     /**
    518      * Returns the id of the view to align with, or {@link android.view.View#NO_ID} for the root
    519      * {@link RecyclerView.ViewHolder#itemView}.
    520      * @return The id of the view to align with, or {@link android.view.View#NO_ID} for the root
    521      * {@link RecyclerView.ViewHolder#itemView}.
    522      */
    523     public int getItemAlignmentViewId() {
    524         return mLayoutManager.getItemAlignmentViewId();
    525     }
    526 
    527     /**
    528      * Sets the spacing in pixels between two child items.
    529      * @deprecated use {@link #setItemSpacing(int)}
    530      */
    531     @Deprecated
    532     public void setItemMargin(int margin) {
    533         setItemSpacing(margin);
    534     }
    535 
    536     /**
    537      * Sets the vertical and horizontal spacing in pixels between two child items.
    538      * @param spacing Vertical and horizontal spacing in pixels between two child items.
    539      */
    540     public void setItemSpacing(int spacing) {
    541         mLayoutManager.setItemSpacing(spacing);
    542         requestLayout();
    543     }
    544 
    545     /**
    546      * Sets the spacing in pixels between two child items vertically.
    547      * @deprecated Use {@link #setVerticalSpacing(int)}
    548      */
    549     @Deprecated
    550     public void setVerticalMargin(int margin) {
    551         setVerticalSpacing(margin);
    552     }
    553 
    554     /**
    555      * Returns the spacing in pixels between two child items vertically.
    556      * @deprecated Use {@link #getVerticalSpacing()}
    557      */
    558     @Deprecated
    559     public int getVerticalMargin() {
    560         return mLayoutManager.getVerticalSpacing();
    561     }
    562 
    563     /**
    564      * Sets the spacing in pixels between two child items horizontally.
    565      * @deprecated Use {@link #setHorizontalSpacing(int)}
    566      */
    567     @Deprecated
    568     public void setHorizontalMargin(int margin) {
    569         setHorizontalSpacing(margin);
    570     }
    571 
    572     /**
    573      * Returns the spacing in pixels between two child items horizontally.
    574      * @deprecated Use {@link #getHorizontalSpacing()}
    575      */
    576     @Deprecated
    577     public int getHorizontalMargin() {
    578         return mLayoutManager.getHorizontalSpacing();
    579     }
    580 
    581     /**
    582      * Sets the vertical spacing in pixels between two child items.
    583      * @param spacing Vertical spacing between two child items.
    584      */
    585     public void setVerticalSpacing(int spacing) {
    586         mLayoutManager.setVerticalSpacing(spacing);
    587         requestLayout();
    588     }
    589 
    590     /**
    591      * Returns the vertical spacing in pixels between two child items.
    592      * @return The vertical spacing in pixels between two child items.
    593      */
    594     public int getVerticalSpacing() {
    595         return mLayoutManager.getVerticalSpacing();
    596     }
    597 
    598     /**
    599      * Sets the horizontal spacing in pixels between two child items.
    600      * @param spacing Horizontal spacing in pixels between two child items.
    601      */
    602     public void setHorizontalSpacing(int spacing) {
    603         mLayoutManager.setHorizontalSpacing(spacing);
    604         requestLayout();
    605     }
    606 
    607     /**
    608      * Returns the horizontal spacing in pixels between two child items.
    609      * @return The Horizontal spacing in pixels between two child items.
    610      */
    611     public int getHorizontalSpacing() {
    612         return mLayoutManager.getHorizontalSpacing();
    613     }
    614 
    615     /**
    616      * Registers a callback to be invoked when an item in BaseGridView has
    617      * been laid out.
    618      *
    619      * @param listener The listener to be invoked.
    620      */
    621     public void setOnChildLaidOutListener(OnChildLaidOutListener listener) {
    622         mLayoutManager.setOnChildLaidOutListener(listener);
    623     }
    624 
    625     /**
    626      * Registers a callback to be invoked when an item in BaseGridView has
    627      * been selected.  Note that the listener may be invoked when there is a
    628      * layout pending on the view, affording the listener an opportunity to
    629      * adjust the upcoming layout based on the selection state.
    630      *
    631      * @param listener The listener to be invoked.
    632      */
    633     public void setOnChildSelectedListener(OnChildSelectedListener listener) {
    634         mLayoutManager.setOnChildSelectedListener(listener);
    635     }
    636 
    637     /**
    638      * Registers a callback to be invoked when an item in BaseGridView has
    639      * been selected.  Note that the listener may be invoked when there is a
    640      * layout pending on the view, affording the listener an opportunity to
    641      * adjust the upcoming layout based on the selection state.
    642      * This method will clear all existing listeners added by
    643      * {@link #addOnChildViewHolderSelectedListener}.
    644      *
    645      * @param listener The listener to be invoked.
    646      */
    647     public void setOnChildViewHolderSelectedListener(OnChildViewHolderSelectedListener listener) {
    648         mLayoutManager.setOnChildViewHolderSelectedListener(listener);
    649     }
    650 
    651     /**
    652      * Registers a callback to be invoked when an item in BaseGridView has
    653      * been selected.  Note that the listener may be invoked when there is a
    654      * layout pending on the view, affording the listener an opportunity to
    655      * adjust the upcoming layout based on the selection state.
    656      *
    657      * @param listener The listener to be invoked.
    658      */
    659     public void addOnChildViewHolderSelectedListener(OnChildViewHolderSelectedListener listener) {
    660         mLayoutManager.addOnChildViewHolderSelectedListener(listener);
    661     }
    662 
    663     /**
    664      * Remove the callback invoked when an item in BaseGridView has been selected.
    665      *
    666      * @param listener The listener to be removed.
    667      */
    668     public void removeOnChildViewHolderSelectedListener(OnChildViewHolderSelectedListener listener)
    669             {
    670         mLayoutManager.removeOnChildViewHolderSelectedListener(listener);
    671     }
    672 
    673     /**
    674      * Changes the selected item immediately without animation.
    675      */
    676     public void setSelectedPosition(int position) {
    677         mLayoutManager.setSelection(position, 0);
    678     }
    679 
    680     /**
    681      * Changes the selected item and/or subposition immediately without animation.
    682      * @hide
    683      */
    684     @RestrictTo(LIBRARY_GROUP)
    685     public void setSelectedPositionWithSub(int position, int subposition) {
    686         mLayoutManager.setSelectionWithSub(position, subposition, 0);
    687     }
    688 
    689     /**
    690      * Changes the selected item immediately without animation, scrollExtra is
    691      * applied in primary scroll direction.  The scrollExtra will be kept until
    692      * another {@link #setSelectedPosition} or {@link #setSelectedPositionSmooth} call.
    693      */
    694     public void setSelectedPosition(int position, int scrollExtra) {
    695         mLayoutManager.setSelection(position, scrollExtra);
    696     }
    697 
    698     /**
    699      * Changes the selected item and/or subposition immediately without animation, scrollExtra is
    700      * applied in primary scroll direction.  The scrollExtra will be kept until
    701      * another {@link #setSelectedPosition} or {@link #setSelectedPositionSmooth} call.
    702      * @hide
    703      */
    704     @RestrictTo(LIBRARY_GROUP)
    705     public void setSelectedPositionWithSub(int position, int subposition, int scrollExtra) {
    706         mLayoutManager.setSelectionWithSub(position, subposition, scrollExtra);
    707     }
    708 
    709     /**
    710      * Changes the selected item and run an animation to scroll to the target
    711      * position.
    712      * @param position Adapter position of the item to select.
    713      */
    714     public void setSelectedPositionSmooth(int position) {
    715         mLayoutManager.setSelectionSmooth(position);
    716     }
    717 
    718     /**
    719      * Changes the selected item and/or subposition, runs an animation to scroll to the target
    720      * position.
    721      * @hide
    722      */
    723     @RestrictTo(LIBRARY_GROUP)
    724     public void setSelectedPositionSmoothWithSub(int position, int subposition) {
    725         mLayoutManager.setSelectionSmoothWithSub(position, subposition);
    726     }
    727 
    728     /**
    729      * Perform a task on ViewHolder at given position after smooth scrolling to it.
    730      * @param position Position of item in adapter.
    731      * @param task Task to executed on the ViewHolder at a given position.
    732      */
    733     public void setSelectedPositionSmooth(final int position, final ViewHolderTask task) {
    734         if (task != null) {
    735             RecyclerView.ViewHolder vh = findViewHolderForPosition(position);
    736             if (vh == null || hasPendingAdapterUpdates()) {
    737                 addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {
    738                     @Override
    739                     public void onChildViewHolderSelected(RecyclerView parent,
    740                             RecyclerView.ViewHolder child, int selectedPosition, int subposition) {
    741                         if (selectedPosition == position) {
    742                             removeOnChildViewHolderSelectedListener(this);
    743                             task.run(child);
    744                         }
    745                     }
    746                 });
    747             } else {
    748                 task.run(vh);
    749             }
    750         }
    751         setSelectedPositionSmooth(position);
    752     }
    753 
    754     /**
    755      * Perform a task on ViewHolder at given position after scroll to it.
    756      * @param position Position of item in adapter.
    757      * @param task Task to executed on the ViewHolder at a given position.
    758      */
    759     public void setSelectedPosition(final int position, final ViewHolderTask task) {
    760         if (task != null) {
    761             RecyclerView.ViewHolder vh = findViewHolderForPosition(position);
    762             if (vh == null || hasPendingAdapterUpdates()) {
    763                 addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {
    764                     @Override
    765                     public void onChildViewHolderSelectedAndPositioned(RecyclerView parent,
    766                             RecyclerView.ViewHolder child, int selectedPosition, int subposition) {
    767                         if (selectedPosition == position) {
    768                             removeOnChildViewHolderSelectedListener(this);
    769                             task.run(child);
    770                         }
    771                     }
    772                 });
    773             } else {
    774                 task.run(vh);
    775             }
    776         }
    777         setSelectedPosition(position);
    778     }
    779 
    780     /**
    781      * Returns the adapter position of selected item.
    782      * @return The adapter position of selected item.
    783      */
    784     public int getSelectedPosition() {
    785         return mLayoutManager.getSelection();
    786     }
    787 
    788     /**
    789      * Returns the sub selected item position started from zero.  An item can have
    790      * multiple {@link ItemAlignmentFacet}s provided by {@link RecyclerView.ViewHolder}
    791      * or {@link FacetProviderAdapter}.  Zero is returned when no {@link ItemAlignmentFacet}
    792      * is defined.
    793      * @hide
    794      */
    795     @RestrictTo(LIBRARY_GROUP)
    796     public int getSelectedSubPosition() {
    797         return mLayoutManager.getSubSelection();
    798     }
    799 
    800     /**
    801      * Sets whether ItemAnimator should run when a child changes size or when adding
    802      * or removing a child.
    803      * @param animateChildLayout True to enable ItemAnimator, false to disable.
    804      */
    805     public void setAnimateChildLayout(boolean animateChildLayout) {
    806         if (mAnimateChildLayout != animateChildLayout) {
    807             mAnimateChildLayout = animateChildLayout;
    808             if (!mAnimateChildLayout) {
    809                 mSavedItemAnimator = getItemAnimator();
    810                 super.setItemAnimator(null);
    811             } else {
    812                 super.setItemAnimator(mSavedItemAnimator);
    813             }
    814         }
    815     }
    816 
    817     /**
    818      * Returns true if an animation will run when a child changes size or when
    819      * adding or removing a child.
    820      * @return True if ItemAnimator is enabled, false otherwise.
    821      */
    822     public boolean isChildLayoutAnimated() {
    823         return mAnimateChildLayout;
    824     }
    825 
    826     /**
    827      * Sets the gravity used for child view positioning. Defaults to
    828      * GRAVITY_TOP|GRAVITY_START.
    829      *
    830      * @param gravity See {@link android.view.Gravity}
    831      */
    832     public void setGravity(int gravity) {
    833         mLayoutManager.setGravity(gravity);
    834         requestLayout();
    835     }
    836 
    837     @Override
    838     public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
    839         return mLayoutManager.gridOnRequestFocusInDescendants(this, direction,
    840                 previouslyFocusedRect);
    841     }
    842 
    843     /**
    844      * Returns the x/y offsets to final position from current position if the view
    845      * is selected.
    846      *
    847      * @param view The view to get offsets.
    848      * @param offsets offsets[0] holds offset of X, offsets[1] holds offset of Y.
    849      */
    850     public void getViewSelectedOffsets(View view, int[] offsets) {
    851         mLayoutManager.getViewSelectedOffsets(view, offsets);
    852     }
    853 
    854     @Override
    855     public int getChildDrawingOrder(int childCount, int i) {
    856         return mLayoutManager.getChildDrawingOrder(this, childCount, i);
    857     }
    858 
    859     final boolean isChildrenDrawingOrderEnabledInternal() {
    860         return isChildrenDrawingOrderEnabled();
    861     }
    862 
    863     @Override
    864     public View focusSearch(int direction) {
    865         if (isFocused()) {
    866             // focusSearch(int) is called when GridView itself is focused.
    867             // Calling focusSearch(view, int) to get next sibling of current selected child.
    868             View view = mLayoutManager.findViewByPosition(mLayoutManager.getSelection());
    869             if (view != null) {
    870                 return focusSearch(view, direction);
    871             }
    872         }
    873         // otherwise, go to mParent to perform focusSearch
    874         return super.focusSearch(direction);
    875     }
    876 
    877     @Override
    878     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
    879         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    880         mLayoutManager.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    881     }
    882 
    883     /**
    884      * Disables or enables focus search.
    885      * @param disabled True to disable focus search, false to enable.
    886      */
    887     public final void setFocusSearchDisabled(boolean disabled) {
    888         // LayoutManager may detachView and attachView in fastRelayout, it causes RowsFragment
    889         // re-gain focus after a BACK key pressed, so block children focus during transition.
    890         setDescendantFocusability(disabled ? FOCUS_BLOCK_DESCENDANTS: FOCUS_AFTER_DESCENDANTS);
    891         mLayoutManager.setFocusSearchDisabled(disabled);
    892     }
    893 
    894     /**
    895      * Returns true if focus search is disabled.
    896      * @return True if focus search is disabled.
    897      */
    898     public final boolean isFocusSearchDisabled() {
    899         return mLayoutManager.isFocusSearchDisabled();
    900     }
    901 
    902     /**
    903      * Enables or disables layout.  All children will be removed when layout is
    904      * disabled.
    905      * @param layoutEnabled True to enable layout, false otherwise.
    906      */
    907     public void setLayoutEnabled(boolean layoutEnabled) {
    908         mLayoutManager.setLayoutEnabled(layoutEnabled);
    909     }
    910 
    911     /**
    912      * Changes and overrides children's visibility.
    913      * @param visibility See {@link View#getVisibility()}.
    914      */
    915     public void setChildrenVisibility(int visibility) {
    916         mLayoutManager.setChildrenVisibility(visibility);
    917     }
    918 
    919     /**
    920      * Enables or disables pruning of children.  Disable is useful during transition.
    921      * @param pruneChild True to prune children out side visible area, false to enable.
    922      */
    923     public void setPruneChild(boolean pruneChild) {
    924         mLayoutManager.setPruneChild(pruneChild);
    925     }
    926 
    927     /**
    928      * Enables or disables scrolling.  Disable is useful during transition.
    929      * @param scrollEnabled True to enable scroll, false to disable.
    930      */
    931     public void setScrollEnabled(boolean scrollEnabled) {
    932         mLayoutManager.setScrollEnabled(scrollEnabled);
    933     }
    934 
    935     /**
    936      * Returns true if scrolling is enabled, false otherwise.
    937      * @return True if scrolling is enabled, false otherwise.
    938      */
    939     public boolean isScrollEnabled() {
    940         return mLayoutManager.isScrollEnabled();
    941     }
    942 
    943     /**
    944      * Returns true if the view at the given position has a same row sibling
    945      * in front of it.  This will return true if first item view is not created.
    946      *
    947      * @param position Position in adapter.
    948      * @return True if the view at the given position has a same row sibling in front of it.
    949      */
    950     public boolean hasPreviousViewInSameRow(int position) {
    951         return mLayoutManager.hasPreviousViewInSameRow(position);
    952     }
    953 
    954     /**
    955      * Enables or disables the default "focus draw at last" order rule. Default is enabled.
    956      * @param enabled True to draw the selected child at last, false otherwise.
    957      */
    958     public void setFocusDrawingOrderEnabled(boolean enabled) {
    959         super.setChildrenDrawingOrderEnabled(enabled);
    960     }
    961 
    962     /**
    963      * Returns true if draws selected child at last, false otherwise. Default is enabled.
    964      * @return True if draws selected child at last, false otherwise.
    965      */
    966     public boolean isFocusDrawingOrderEnabled() {
    967         return super.isChildrenDrawingOrderEnabled();
    968     }
    969 
    970     /**
    971      * Sets the touch intercept listener.
    972      * @param listener The touch intercept listener.
    973      */
    974     public void setOnTouchInterceptListener(OnTouchInterceptListener listener) {
    975         mOnTouchInterceptListener = listener;
    976     }
    977 
    978     /**
    979      * Sets the generic motion intercept listener.
    980      * @param listener The motion intercept listener.
    981      */
    982     public void setOnMotionInterceptListener(OnMotionInterceptListener listener) {
    983         mOnMotionInterceptListener = listener;
    984     }
    985 
    986     /**
    987      * Sets the key intercept listener.
    988      * @param listener The key intercept listener.
    989      */
    990     public void setOnKeyInterceptListener(OnKeyInterceptListener listener) {
    991         mOnKeyInterceptListener = listener;
    992     }
    993 
    994     /**
    995      * Sets the unhandled key listener.
    996      * @param listener The unhandled key intercept listener.
    997      */
    998     public void setOnUnhandledKeyListener(OnUnhandledKeyListener listener) {
    999         mOnUnhandledKeyListener = listener;
   1000     }
   1001 
   1002     /**
   1003      * Returns the unhandled key listener.
   1004      * @return The unhandled key listener.
   1005      */
   1006     public OnUnhandledKeyListener getOnUnhandledKeyListener() {
   1007         return mOnUnhandledKeyListener;
   1008     }
   1009 
   1010     @Override
   1011     public boolean dispatchKeyEvent(KeyEvent event) {
   1012         if (mOnKeyInterceptListener != null && mOnKeyInterceptListener.onInterceptKeyEvent(event)) {
   1013             return true;
   1014         }
   1015         if (super.dispatchKeyEvent(event)) {
   1016             return true;
   1017         }
   1018         return mOnUnhandledKeyListener != null && mOnUnhandledKeyListener.onUnhandledKey(event);
   1019     }
   1020 
   1021     @Override
   1022     public boolean dispatchTouchEvent(MotionEvent event) {
   1023         if (mOnTouchInterceptListener != null) {
   1024             if (mOnTouchInterceptListener.onInterceptTouchEvent(event)) {
   1025                 return true;
   1026             }
   1027         }
   1028         return super.dispatchTouchEvent(event);
   1029     }
   1030 
   1031     @Override
   1032     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
   1033         if (mOnMotionInterceptListener != null) {
   1034             if (mOnMotionInterceptListener.onInterceptMotionEvent(event)) {
   1035                 return true;
   1036             }
   1037         }
   1038         return super.dispatchGenericFocusedEvent(event);
   1039     }
   1040 
   1041     /**
   1042      * Returns the policy for saving children.
   1043      *
   1044      * @return policy, one of {@link #SAVE_NO_CHILD}
   1045      * {@link #SAVE_ON_SCREEN_CHILD} {@link #SAVE_LIMITED_CHILD} {@link #SAVE_ALL_CHILD}.
   1046      */
   1047     public final int getSaveChildrenPolicy() {
   1048         return mLayoutManager.mChildrenStates.getSavePolicy();
   1049     }
   1050 
   1051     /**
   1052      * Returns the limit used when when {@link #getSaveChildrenPolicy()} is
   1053      *         {@link #SAVE_LIMITED_CHILD}
   1054      */
   1055     public final int getSaveChildrenLimitNumber() {
   1056         return mLayoutManager.mChildrenStates.getLimitNumber();
   1057     }
   1058 
   1059     /**
   1060      * Sets the policy for saving children.
   1061      * @param savePolicy One of {@link #SAVE_NO_CHILD} {@link #SAVE_ON_SCREEN_CHILD}
   1062      * {@link #SAVE_LIMITED_CHILD} {@link #SAVE_ALL_CHILD}.
   1063      */
   1064     public final void setSaveChildrenPolicy(int savePolicy) {
   1065         mLayoutManager.mChildrenStates.setSavePolicy(savePolicy);
   1066     }
   1067 
   1068     /**
   1069      * Sets the limit number when {@link #getSaveChildrenPolicy()} is {@link #SAVE_LIMITED_CHILD}.
   1070      */
   1071     public final void setSaveChildrenLimitNumber(int limitNumber) {
   1072         mLayoutManager.mChildrenStates.setLimitNumber(limitNumber);
   1073     }
   1074 
   1075     @Override
   1076     public boolean hasOverlappingRendering() {
   1077         return mHasOverlappingRendering;
   1078     }
   1079 
   1080     public void setHasOverlappingRendering(boolean hasOverlapping) {
   1081         mHasOverlappingRendering = hasOverlapping;
   1082     }
   1083 
   1084     /**
   1085      * Notify layout manager that layout directionality has been updated
   1086      */
   1087     @Override
   1088     public void onRtlPropertiesChanged(int layoutDirection) {
   1089         mLayoutManager.onRtlPropertiesChanged(layoutDirection);
   1090     }
   1091 
   1092     @Override
   1093     public void setRecyclerListener(RecyclerView.RecyclerListener listener) {
   1094         mChainedRecyclerListener = listener;
   1095     }
   1096 
   1097     /**
   1098      * Sets pixels of extra space for layout child in invisible area.
   1099      *
   1100      * @param extraLayoutSpace  Pixels of extra space for layout invisible child.
   1101      *                          Must be bigger or equals to 0.
   1102      * @hide
   1103      */
   1104     @RestrictTo(LIBRARY_GROUP)
   1105     public void setExtraLayoutSpace(int extraLayoutSpace) {
   1106         mLayoutManager.setExtraLayoutSpace(extraLayoutSpace);
   1107     }
   1108 
   1109     /**
   1110      * Returns pixels of extra space for layout child in invisible area.
   1111      *
   1112      * @hide
   1113      */
   1114     @RestrictTo(LIBRARY_GROUP)
   1115     public int getExtraLayoutSpace() {
   1116         return mLayoutManager.getExtraLayoutSpace();
   1117     }
   1118 
   1119     /**
   1120      * Temporarily slide out child views to bottom (for VerticalGridView) or end
   1121      * (for HorizontalGridView). Layout and scrolling will be suppressed until
   1122      * {@link #animateIn()} is called.
   1123      */
   1124     public void animateOut() {
   1125         mLayoutManager.slideOut();
   1126     }
   1127 
   1128     /**
   1129      * Undo animateOut() and slide in child views.
   1130      */
   1131     public void animateIn() {
   1132         mLayoutManager.slideIn();
   1133     }
   1134 
   1135     @Override
   1136     public void scrollToPosition(int position) {
   1137         // dont abort the animateOut() animation, just record the position
   1138         if (mLayoutManager.isSlidingChildViews()) {
   1139             mLayoutManager.setSelectionWithSub(position, 0, 0);
   1140             return;
   1141         }
   1142         super.scrollToPosition(position);
   1143     }
   1144 
   1145     @Override
   1146     public void smoothScrollToPosition(int position) {
   1147         // dont abort the animateOut() animation, just record the position
   1148         if (mLayoutManager.isSlidingChildViews()) {
   1149             mLayoutManager.setSelectionWithSub(position, 0, 0);
   1150             return;
   1151         }
   1152         super.smoothScrollToPosition(position);
   1153     }
   1154 
   1155     /**
   1156      * Sets the number of items to prefetch in
   1157      * {@link RecyclerView.LayoutManager#collectInitialPrefetchPositions(int, RecyclerView.LayoutManager.LayoutPrefetchRegistry)},
   1158      * which defines how many inner items should be prefetched when this GridView is nested inside
   1159      * another RecyclerView.
   1160      *
   1161      * <p>Set this value to the number of items this inner GridView will display when it is
   1162      * first scrolled into the viewport. RecyclerView will attempt to prefetch that number of items
   1163      * so they are ready, avoiding jank as the inner GridView is scrolled into the viewport.</p>
   1164      *
   1165      * <p>For example, take a VerticalGridView of scrolling HorizontalGridViews. The rows always
   1166      * have 6 items visible in them (or 7 if not aligned). Passing <code>6</code> to this method
   1167      * for each inner GridView will enable RecyclerView's prefetching feature to do create/bind work
   1168      * for 6 views within a row early, before it is scrolled on screen, instead of just the default
   1169      * 4.</p>
   1170      *
   1171      * <p>Calling this method does nothing unless the LayoutManager is in a RecyclerView
   1172      * nested in another RecyclerView.</p>
   1173      *
   1174      * <p class="note"><strong>Note:</strong> Setting this value to be larger than the number of
   1175      * views that will be visible in this view can incur unnecessary bind work, and an increase to
   1176      * the number of Views created and in active use.</p>
   1177      *
   1178      * @param itemCount Number of items to prefetch
   1179      *
   1180      * @see #getInitialPrefetchItemCount()
   1181      * @see RecyclerView.LayoutManager#isItemPrefetchEnabled()
   1182      * @see RecyclerView.LayoutManager#collectInitialPrefetchPositions(int, RecyclerView.LayoutManager.LayoutPrefetchRegistry)
   1183      */
   1184     public void setInitialPrefetchItemCount(int itemCount) {
   1185         mInitialPrefetchItemCount = itemCount;
   1186     }
   1187 
   1188     /**
   1189      * Gets the number of items to prefetch in
   1190      * {@link RecyclerView.LayoutManager#collectInitialPrefetchPositions(int, RecyclerView.LayoutManager.LayoutPrefetchRegistry)},
   1191      * which defines how many inner items should be prefetched when this GridView is nested inside
   1192      * another RecyclerView.
   1193      *
   1194      * @see RecyclerView.LayoutManager#isItemPrefetchEnabled()
   1195      * @see #setInitialPrefetchItemCount(int)
   1196      * @see RecyclerView.LayoutManager#collectInitialPrefetchPositions(int, RecyclerView.LayoutManager.LayoutPrefetchRegistry)
   1197      *
   1198      * @return number of items to prefetch.
   1199      */
   1200     public int getInitialPrefetchItemCount() {
   1201         return mInitialPrefetchItemCount;
   1202     }
   1203 }
   1204