How to set the scrollToPositionWithOffset(x,y) of RecyclerView? Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of How to set the scrollToPositionWithOffset(x,y) of RecyclerView? without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I have a RecyclerView fetching data from an API. I am using Volley. I am fetching data in batches of 20 items. I wish to set the scroll position using Linear Layout Manager myLLM.scrollToPositionWithOffset(x,y) so that when next batch of data is fetched the scroll position which currently resets to top is retained at the last item of previous batch.

For this i need to add the following line of code at the place shown in the code below.

myLLM.scrollToPositionWithOffset(y,0);

But i am not able to do so. Please guide me on how achieve this.

public class ActivityItems extends AppCompatActivity {

private RecyclerView myRvItems;
private ItemsAdapter myItemsAdapter;
private ArrayList<ItemsModel> myItemsFeedList;
private RequestQueue myRequestQueue;
private ProgressBar itemsProgressBar;
Boolean isScrolling = false;
int currentItems, totalItems, scrolledOutItems, x = 0, y = (x + 20);

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_items);

    getSupportActionBar().setTitle("Inventory Items");
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    myRvItems = findViewById(R.id.rvItems);
    itemsProgressBar = findViewById(R.id.pbItems);

    final LinearLayoutManager myLLM = new LinearLayoutManager(this);
    myRvItems.setLayoutManager(myLLM);

    myItemsFeedList = new ArrayList<>();
    myRequestQueue = Volley.newRequestQueue(this);

    parseJSON();

    myRvItems.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if(newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
                isScrolling = true;
            }
        }

        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            currentItems = myLLM.getChildCount();
            totalItems = myLLM.getItemCount();
            scrolledOutItems = myLLM.findFirstVisibleItemPosition();

            if(isScrolling && (currentItems + scrolledOutItems == totalItems)){
                isScrolling = false;
                parseJSON();
                myLLM.scrollToPositionWithOffset(4, 20);
            }
        }
    });

}

private void parseJSON() {

    itemsProgressBar.setVisibility(View.VISIBLE);
    String url = "http://restapis.xyv.com/api/list";

    JsonObjectRequest myRequest = new JsonObjectRequest(Request.Method.GET, url, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    try {
                        JSONArray myJSONArray = response.getJSONArray("Data");

                        for (int i = x; i < y && i < myJSONArray.length(); i++){

                            JSONObject myData = myJSONArray.getJSONObject(i);

                            String itemID = myData.getString("ItemID");
                            String itemName = myData.getString("ItemName");
                            String itemRackNo = myData.getString("RackNo");

                            myItemsFeedList.add(new ItemsModel(itemID,itemName,itemRackNo));

    **//   I WANT TO SET THE SCROLL POSITION HERE BUT THIS NOT WORKING**
    **//   myLLM.scrollToPositionWithOffset(y,0);**

                        }

                        myItemsAdapter = new ItemsAdapter(myItemsFeedList,ActivityItems.this );
                        myRvItems.setAdapter(myItemsAdapter);
                        itemsProgressBar.setVisibility(View.GONE);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();
        }
    });

    myRequestQueue.add(myRequest);

}

@Override
public boolean onSupportNavigateUp() {
    onBackPressed();
    return super.onSupportNavigateUp();
}

}

Answer

Following the advice from @mmmcho the issue was solved. “Set your adapter first, even if your list is empty. Update your list when you get the data. Then call adapter.notifydatasetchanged() method.”

There is also a crude way of pagination implemented. So if someone is looking for easiest RecyclerView pagination, he can also follow the code.(Just have your api data sorted by date and it will work best.)

The code now looks like follows:

public class ActivityItems extends AppCompatActivity {

private RecyclerView myRvItems;
private ItemsAdapter myItemsAdapter;
private ArrayList<ItemsModel> myItemsFeedList;
private RequestQueue myRequestQueue;
private ProgressBar itemsProgressBar;
Boolean isScrolling = false;
int currentItems, totalItems, scrolledOutItems, fetchSize = 6 , x = 0, y = (x + fetchSize);

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_items);

    getSupportActionBar().setTitle("Inventory Items");
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    myRvItems = findViewById(R.id.rvItems);
    itemsProgressBar = findViewById(R.id.pbItems);

    final LinearLayoutManager myLLM = new LinearLayoutManager(this);
    myRvItems.setLayoutManager(myLLM);

    myItemsFeedList = new ArrayList<>();
    myItemsAdapter = new ItemsAdapter(myItemsFeedList,ActivityItems.this );
    myRvItems.setAdapter(myItemsAdapter);

    myRequestQueue = Volley.newRequestQueue(this);

    parseJSON();


    myRvItems.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if(newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
                isScrolling = true;
            }
        }

        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            currentItems = myLLM.getChildCount();
            totalItems = myLLM.getItemCount();
            scrolledOutItems = myLLM.findFirstVisibleItemPosition();

            if(isScrolling && (currentItems + scrolledOutItems == totalItems)){
                isScrolling = false;
                y = x + fetchSize;
                parseJSON();

            }
        }
    });

}

private void parseJSON() {

    itemsProgressBar.setVisibility(View.VISIBLE);
    String url = "http://restapis.xyn.com/api/list";

    JsonObjectRequest myRequest = new JsonObjectRequest(Request.Method.GET, url, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    try {
                        JSONArray myJSONArray = response.getJSONArray("Data");

                        for (int i = x; i < y && i < myJSONArray.length(); i++){

                            JSONObject myData = myJSONArray.getJSONObject(i);

                            String itemID = myData.getString("ItemID");
                            String itemName = myData.getString("ItemName");
                            String itemRackNo = myData.getString("RackNo");

                            myItemsFeedList.add(new ItemsModel(itemID,itemName,itemRackNo));
                            x = x+1;
                        }

                        myItemsAdapter.notifyDataSetChanged();
                        itemsProgressBar.setVisibility(View.GONE);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();
        }
    });

    myRequestQueue.add(myRequest);

}

@Override
public boolean onSupportNavigateUp() {
    onBackPressed();
    return super.onSupportNavigateUp();
}}
We are here to answer your question about How to set the scrollToPositionWithOffset(x,y) of RecyclerView? - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji