18

I have this code:

mRecycleView.setOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int[] firstVisibleItemPositions = new int[getResources().getInteger(R.integer.news_numbers_column)]; 
        int pastVisiblesItems = ((StaggeredGridLayoutManager)getLayoutManager()).findFirstVisibleItemPositions(firstVisibleItemPositions)[0];
    }
});

When I scroll my recycleview I get this error:

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.support.v7.widget.OrientationHelper.getStartAfterPadding()' on a null object reference
at android.support.v7.widget.StaggeredGridLayoutManager$Span.findOneVisibleChild(StaggeredGridLayoutManager.java:2177)
at android.support.v7.widget.StaggeredGridLayoutManager$Span.findFirstVisibleItemPosition(StaggeredGridLayoutManager.java:2153)
at android.support.v7.widget.StaggeredGridLayoutManager.findFirstVisibleItemPositions(StaggeredGridLayoutManager.java:806)
at info.lanouvelletribune.apps.android.ui.fragments.NewsFragment$1.onScrollStateChanged(NewsFragment.java:90)
at android.support.v7.widget.RecyclerView.setScrollState(RecyclerView.java:751)
at android.support.v7.widget.RecyclerView.onInterceptTouchEvent(RecyclerView.java:1535)
at com.github.ksoichiro.android.observablescrollview.ObservableRecyclerView.onInterceptTouchEvent(ObservableRecyclerView.java:188)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2060)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2390)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1741)
at android.app.Activity.dispatchTouchEvent(Activity.java:2826)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2351)
at android.view.View.dispatchPointerEvent(View.java:8590)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4098)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3964)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3488)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3541)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3515)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3488)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3541)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3617)
at android

How can I do to handle this error and get the first visible item position?

Suhaib Janjua
  • 3,538
  • 16
  • 59
  • 73
user3535747
  • 253
  • 1
  • 2
  • 7
  • I guess it is happening at the very first initialization. For now, check if it has any children before calling findFirstVisible and also it would be nice if you can create a bug report on b.android.com . – yigit Apr 07 '15 at 04:42

7 Answers7

40

I tested it with this code and it works fine with me

int positionView = ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition();

I used the recycle view parameter.

Piyush
  • 18,895
  • 5
  • 32
  • 63
zed007
  • 464
  • 6
  • 6
  • In case you are using something like StaggeredGridLayoutManager(), then the signature of the method changes. {currentScrollPosition = (recyclerView?.layoutManager as StaggeredGridLayoutManager) .findLastCompletelyVisibleItemPositions(intArrayOf(0,1))[1]} – Sahil Patel Apr 08 '18 at 07:08
  • 2
    for kotlin use `val positionView = (recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()` – Abduhafiz Oct 20 '19 at 08:47
7

Try this:

int position = layoutManager.findFirstVisibleItemPositions(null)[0];

where layoutManager is what you set in your recyclerview.

For example,

layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mrecyclerView.setLayoutManager(layoutManager );
Piyush
  • 18,895
  • 5
  • 32
  • 63
Ankit Aggarwal
  • 2,941
  • 2
  • 17
  • 26
  • this solution worked for me. please tell me if there is something wrong in the solution. layoutManager.findFirstVisibleItemPositions(null) will return a new array. [link](https://developer.android.com/reference/android/support/v7/widget/StaggeredGridLayoutManager.html#findFirstVisibleItemPositions(int[])) – Ankit Aggarwal Apr 09 '15 at 11:01
3

Use these two methods :

    /**
     * @return Last visible item position for staggeredGridLayoutManager
     */
    private int getLastVisibleItem(int[] lastVisibleItemPositions) {
        int maxSize = 0;
        for (int position : lastVisibleItemPositions) {
            if (position > maxSize) {
                maxSize = position;
            }
        }
        return maxSize;
    }

    /**
     * @return First visible item position for staggeredGridLayoutManager
     */
    private int getFirstVisibleItem(int[] firstVisibleItemPositions) {
        int minSize = 0;
        if (firstVisibleItemPositions.length > 0) {
            minSize = firstVisibleItemPositions[0];
            for (int position : firstVisibleItemPositions) {
                if (position < minSize) {
                    minSize = position;
                }
            }
        }
        return minSize;
    }

and getLastVisibleItem method as below:

                    int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null);
                    int[] firstVisibleItemPositions = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(null);
                    // get maximum element within the list
                    lastVisibleItem = getLastVisibleItem(lastVisibleItemPositions);
                    firstVisibleItem = getFirstVisibleItem(firstVisibleItemPositions);
smarteist
  • 1,331
  • 12
  • 15
1

You can use this :

int[] firstVisibleItemPositions = new int[yourNumberOfColumns];
int pastVisiblesItems = layoutManager.findFirstVisibleItemPositions(firstVisibleItem‌​Positions)[0];
user3793358
  • 31
  • 1
  • 5
0

This is a bug in the RecyclerView StaggeredGridLayoutManager:

https://code.google.com/p/android/issues/detail?id=180521

https://code.google.com/p/android/issues/detail?id=181461

A workaround is to try/catch the exception:

try {
    ((StaggeredGridLayoutManager)getLayoutManager()).findFirstVisibleItemPositions(firstVisibleItemPositions);
} catch (NullPointerException ex) {
    // workaround for RecyclerView bug. assume not laid out, so no items visible
    firstVisibleItemPositions[0] = RecyclerView.NO_POSITION;
    firstVisibleItemPositions[1] = RecyclerView.NO_POSITION;
}
TalkLittle
  • 8,866
  • 6
  • 54
  • 51
0

If you are using StaggeredGridLayoutManager you can find findLastVisibleItemPositions like below:

int visibleThreshold =1;
final StaggeredGridLayoutManager linearLayoutManager = (StaggeredGridLayoutManager) mRecyclerViewAllPost.getLayoutManager();
    mRecyclerViewAllPost.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            int[] lastVisibleItemPositions = linearLayoutManager.findLastVisibleItemPositions(null);
            int lastVisibleItem = getLastVisibleItem(lastVisibleItemPositions);
            int totalItemCount = linearLayoutManager.getItemCount();
            if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                print("load more item ");
                isLoading = true;
            }
        }
    });

and getLastVisibleItem method as below:

public int getLastVisibleItem(int[] lastVisibleItemPositions) {
    int maxSize = 0;
    for (int i = 0; i < lastVisibleItemPositions.length; i++) {
        if (i == 0) {
            maxSize = lastVisibleItemPositions[i];
        }
        else if (lastVisibleItemPositions[i] > maxSize) {
            maxSize = lastVisibleItemPositions[i];
        }
    }
    return maxSize;
}
varotariya vajsi
  • 3,965
  • 37
  • 39
  • please can you tell me that if implement this method where can i put this 'new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)' – Vasant Raval Jul 13 '21 at 05:28
  • @VasantRaval layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL); mrecyclerView.setLayoutManager(layoutManager ); https://stackoverflow.com/a/29529952/2897365 – varotariya vajsi Aug 20 '21 at 09:22
0

You can try it this way:

StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();

Or you can use your staggeredlayoutManager object directly instead of above object:

int[] into = staggeredGridLayoutManager .findLastVisibleItemPositions(null);
List<Integer> intoList = new ArrayList<>();

for (int i : into) 
{
 intoList.add(i);
}



int firstVisbleoitem= Collections.max(intoList);