Android’s RecyclerView LayoutManager’s Find By Visibility Methods
Got bit by this today so I figured I’d share the knowledge. If you are trying to get a first, last, or completely visible item position from Android’s new RecyclerView LinearLayoutManager using their corresponding method be aware that it can return -1. If no views are laid out that satisfy LinearLayoutManager’s visibility requirement then it will return the static int NO_POSITION value of -1. The method declaration reads:
public static final int NO_POSITION = -1;.../**
* Returns the adapter position of the first visible view.
* <p>
* Note that, this value is not affected by layout orientation or item order traversal.
* ({@link #setReverseLayout(boolean)}). Views are sorted by their positions in the adapter,
* not in the layout.
* <p>
* If RecyclerView has item decorators, they will be considered in calculations as well.
* <p>
* LayoutManager may pre-cache some views that are not necessarily visible. Those views
* are ignored in this method.
*
* @return The adapter position of the first visible item or {@link RecyclerView#NO_POSITION} if
* there aren't any visible items.
* @see #findFirstCompletelyVisibleItemPosition()
* @see #findLastVisibleItemPosition()
*/
public int findFirstVisibleItemPosition() {
final View child = findOneVisibleChild(0, getChildCount(), false);
return child == null ? NO_POSITION : getPosition(child);
}
If you then attempt to grab the value from your adapter by position you’ll undoubtedly run into an ArrayIndexOutOfBoundsException. I’m not advocating manipulating / restoring RecyclerView state manually (as an example). But if you such a thing is necessary, make sure to make the position calls after your RecyclerView has laid out or be defensive with your array access.