13

How do I scroll to a particular position with an offset inside recyclerview?

I have used

public LinearLayoutManager linearlayoutmanager;
linearlayoutmanager.scrollToPositionWithOffset(0, scrolled);

Also I have used scrollto

mRecyclerView.scrollTo(0, scrolled);

Also I have used smoothScrolltoposition

mRecyclerView.smoothScrollToPosition(scrolled);

But none seems to working for me.

If anyone knows anything about this please could you help me

UPDATE

Function where i am setting adapter of my Recyclerview

public void Nearby_Search_requestData() {
    OkHttpClient client = new OkHttpClient();
    client = MySSLTrust.trustcert(getActivity());

    RestAdapter adapter = new RestAdapter.Builder().setEndpoint(SEARCH_MERCHANT_ENDPOINT).setClient(new OkClient(client)).build();
    final RetrofitInterface api = adapter.create(RetrofitInterface.class);
    if (api != null) {
        api.post_Nearby_Search(page.toString(), new Callback<Nearby_Search_All>() {
            @Override
            public void success(final Nearby_Search_All server_data, Response response) {
                if (server_data.getSuccess() == 1) {
                    if (server_data.getResults().size() == 0) {
                        if (page != 0) {
                            mRecyclerView.scrollToPosition(firstVis);
                        } else {
                            Log.d("hii", "zero");
            //                NO_MERCHANT.setVisibility(View.VISIBLE);
                            mAdapter = new searchrecyclerviewadapter(getActivity(), data, font);
                            mRecyclerView.setAdapter(mAdapter);
                        }
                    } else {
                        Log.d("scroll", "hii");
            //            NO_MERCHANT.setVisibility(View.INVISIBLE);
                        if (server_data.getSize() > server_data.getResults().size()) {
                            stay_on_this_page = true;
                        } else {
                            stay_on_this_page = false;
                        }
                        if (page == 0) {
                            prev_total = 0;
                            data.clear();
                            Log.d("hii", "Page is zero " + prev_total);
                            list_size = server_data.getSize();
                        } else {
                            Log.d("hii", "prev_total is " + prev_total + " Size is " + server_data.getSize() + " page is " + page);
                            prev_total = server_data.getSize() * page;
                            Log.d("hii", "Now prev_total is " + prev_total);
                        }
                        total_curr = server_data.getResults().size();

                        Log.d("hii", "first place is " + server_data.getResults().get(0).getShop_name());

                        for (int i = 0; i < total_curr; i++) {
                            information current = new information();
                            current.title = server_data.getResults().get(i).getShop_name();
                            String street = server_data.getResults().get(i).getAddress().getStreet();
                            String area = server_data.getResults().get(i).getAddress().getArea();
                            current.Address = street + " " + area;
                            String[] splited = area.split(",");
                            current.area1 = splited[1];
                            current.type = server_data.getResults().get(i).getShop_type();
                            current.rating = server_data.getResults().get(i).getRating();
                            current.distance = server_data.getResults().get(i).getDistance();
                            current.jeb_no = server_data.getResults().get(i).getJeb_no();
                            current.total_photos = server_data.getResults().get(i).getTotal_photos();
                            if (current.total_photos  == 0) {

                            } else if (current.total_photos  == 1) {
                                current.photo_1 = server_data.getResults().get(i).getPhotos().getPhoto_1();
                            } else if (current.total_photos  == 2) {
                                current.photo_1 = server_data.getResults().get(i).getPhotos().getPhoto_1();
                                current.photo_2 = server_data.getResults().get(i).getPhotos().getPhoto_2();
                            } else {
                                current.photo_1 = server_data.getResults().get(i).getPhotos().getPhoto_1();
                                current.photo_2 = server_data.getResults().get(i).getPhotos().getPhoto_2();
                            }
                            data.add(current);
                        }
                        if (adapterinitialised) {
                            mAdapter.notifyDataSetChanged();
                        } else {
                            mAdapter = new searchrecyclerviewadapter(getActivity(), data, font);
                          //  mAdapter.setClickListener(Search.class);
                            mRecyclerView.setAdapter(mAdapter);

                            adapterinitialised = true;
                        }
                    }
                 //   mRecyclerView.scrollToPosition(firstVis);
                    Log.d("scroll", "hee");
                    scrolled = scrolled + 10;
                    Log.d("scroll", "scrolled: " + scrolled);
                    // ALL BELOW CODE I HAVE TRIED FOR SCROLLING BUT NONE WAS HELPFUL
                /*    mRecyclerView.post(new Runnable() {
                        @Override
                        public void run() {
                            mRecyclerView.smoothScrollToPosition(scrolled);

                            // or do mRecyclerView.scrollTo(0, scrolled);
                        }
                    });
                    */
                 //   l.scrollToPositionWithOffset(0, scrolled);
                //    mRecyclerView.smoothScrollToPosition(scrolled);
                //    mRecyclerView.scrollBy(0, scrolled);
                //    l.scrollToPosition();
                //        mRecyclerView.scrollToPosition(scrolled);
                //    mRecyclerView.smoothScrollBy(0, scrolled);
                //    mRecyclerView.scrollBy(0, 10);
                //    mRecyclerView.scrollTo(0, 10);

                } else {
                    Log.d("hii", server_data.getMessage());
                    Toast.makeText(getActivity(), server_data.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void failure(RetrofitError retrofitError) {
                Log.d("hii", "failure");
                Log.e("hii", retrofitError.toString());
                Toast.makeText(getActivity(), retrofitError.toString(), Toast.LENGTH_SHORT).show();
            }
        });
    } else {
        Log.d("hii", "api null");
    }
}
aman verma
  • 732
  • 1
  • 8
  • 26

5 Answers5

12

Here is my answer. Set

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);//or HORIZONTAL
recyclerView.setLayoutManager(linearLayoutManager);
adapter = new Adapter(...);
recyclerView.setAdapter(adapter);

This provides direction of your RecyclerView, adapter and data (replace ... with context, list, array or another data needed). Than set

linearLayoutManager.scrollToPositionWithOffset(position, offset);

Now the interesting thing:

  • this will scroll to position and place it at the top of the list in case of VERTICAL linear layout manager an at the left with HORIZONTAL
  • if offset is positive, VERTICAL layout manager will scroll this position downwards by offset in pixels (rightwards with HORIZONTAL layout manager)
  • if position is 0 and offset is positive, than nothing will happen, because RecyclerView does not have any items positioned at the top of your 0 position (at the left with HORIZONTAL layout manager)
  • if position is 0 and offset is negative, than VERTICAL layout manager will scroll 0 position upwards by offset in pixels (leftwards with HORIZONTAL)
  • also nothing will happen if RecyclerView's height (width with HORIZONTAL orientation) is smaller than screen size
  • also it will scroll wrongly if position to scroll to is last or near the end and its height (width in case of HORIZONTAL orientation) is relatively small

Hope this will clarify situation for you with RecyclerView's layout manager

Roman T.
  • 333
  • 3
  • 10
  • It's interesting that only `scrollToPositionWithOffset` works, instead of for example `recyclerView.scrollTo` or `scrollBy`. However, how to solve the issues when near to the bottom? I have issues in these cases - doesn't have to be super-near to the bottom, starts at a fairly large distance - and the height isn't that small. – User Jul 06 '18 at 16:07
  • 1
    I mean isn't there any method to scroll a recycler view (more specifically when initialized - appears to work in other cases) reliably? This is crazy... – User Jul 06 '18 at 16:07
  • I didn't understood your requirements ("However, how to solve the issues when near to the bottom"), but quick suggestion is to add padding to recyclerview for bottom and add clipToPadding=false to scroll pass the bottom item. And, if my answer was "correct" - please mark it as corect. – Roman T. Mar 07 '19 at 10:06
  • @aman verma, please consider to mark my answer as correct if it resolves your question – Roman T. Jun 23 '20 at 21:03
3

I believe what your looking for is to run this scroll but do so by posting a runnable on your RecyclerView and run the smoothScrollToPosition there:

 // use either post or postDelayed
 mRecyclerView.postDelayed(new Runnable() {
        @Override
        public void run() {
            mRecyclerView.smoothScrollToPosition(scrolled);

            // or do mRecyclerView.scrollTo(0, scrolled);
        }
    }, 1000);

if you would like to skip the delay:

 mRecyclerView.post(new Runnable() {
        @Override
        public void run() {
            mRecyclerView.smoothScrollToPosition(scrolled);

            // or do mRecyclerView.scrollTo(0, scrolled);
        }
    });
kandroidj
  • 13,784
  • 5
  • 64
  • 76
  • i don't get it, why are you using threads why doesn't just mRecyclerView.smoothScrollToPosition(scrolled) work ?? – aman verma Dec 14 '15 at 17:14
  • @amanverma creating a new Runnable does not use a new Thread unless you explicitly pass that Runnable to a Thread – kandroidj Dec 14 '15 at 17:15
  • yea but why using this doesnt mRecyclerView.smoothScrollToPosition(scrolled) alone sufficient why use runnable ?? – aman verma Dec 14 '15 at 17:17
  • @amanverma in simplistic terms, the UI is not ready to scroll to a position as its setting up, so posting a new Runnable to do the work will account for this. please see http://stackoverflow.com/questions/11431832/android-smoothscrolltoposition-not-working-correctly – kandroidj Dec 14 '15 at 17:19
  • Yep this is working but i dot know why normal scrolltoposition is not working also scrolling is happening but after some seconds can you pls tell me why is this happeing and how to remove this. – aman verma Dec 14 '15 at 17:34
  • @amanverma this is due to the postDelayed method, and the 1000 which is 1 second delay. if you just switch to post(new Runnable(){...}) dropping the millis argument, it should happen fairly quickly, and if your list is short you may not see the effect of it – kandroidj Dec 14 '15 at 17:37
  • but it is taking some time ?? thats why i dont wanna use runable but dont know how to do this ?? – aman verma Dec 14 '15 at 18:10
  • @amanverma please see the updated answer where i show the post method, this does not take some time – kandroidj Dec 14 '15 at 18:17
1

This works for me:

recyclerView.postDelayed(new Runnable() {
    @Override
    public void run() {
        recyclerView.smoothScrollToPosition(0);
    }
}, 10);


recyclerView.post(new Runnable() {
    @Override
    public void run() {
        recyclerView.smoothScrollToPosition(0);
    }
});
Zhming
  • 333
  • 3
  • 12
-1

According with the documentation you should use scrollToPosition.

http://developer.android.com/reference/android/support/v7/widget/RecyclerView.html#scrollToPosition(int)

  • i have used but it didn't work public LinearLayoutManager linearlayoutmanager; linearlayoutmanager.scrollToPositionWithOffset(0, scrolled); – aman verma Dec 14 '15 at 16:37
  • but i also need an offset – aman verma Dec 14 '15 at 16:38
  • The offset start from 0, right? You can keep the position in a variable, and when you scroll your offset shoud be: offset + getPosition of http://developer.android.com/reference/android/support/v7/widget/RecyclerView.LayoutManager.html#getPosition(android.view.View) – AndroidRuntimeException Dec 14 '15 at 16:46
  • Check this post http://stackoverflow.com/questions/26875061/scroll-recyclerview-to-show-selected-item-on-top – AndroidRuntimeException Dec 14 '15 at 16:58
-3

This may work

mRecyclerView.scrollToPosition(0);

0, in this case, represents the position in the adapter

Michael
  • 9,639
  • 3
  • 64
  • 69