Pagination on Horizontal RecyclerView android – AndroidWave

Pagination on Horizontal RecyclerView android

This article provides you with a complete solution of pagination of horizontal RecyclerView along with source code. We tried to give our best solution for horizontal RecyclerView pagination. If you feel any improvement please put your comment inside comment box.

Prerequisite

In this demo, I will use RecyclerView, Horizontal SwipeRefreshLayout, Retrofit, Rest API with pagination.

Implementation Step of Pagination on Horizontal RecyclerView

Let’s follow above step

Pagination on Horizontal RecyclerView android (Sample APP)

1. Create and setup projects

Let’s move the Android Studio and create a new project with EmptyActivity template. For do that go the file menu and create a new project fill info like name and package name.

2. Write a POJO class for list item

In project main folder create a new model class and create entity such as ID, Main Title etc.

package com.wave.pagination.recyclerview.model;

import com.google.gson.annotations.SerializedName;

public class NewsItem {

@SerializedName(“created_at”)

private String mCreatedAt;

@SerializedName(“id”)

private String mId;

@SerializedName(“main_title”)

private String mMainTitle;

@SerializedName(“media_url”)

private String mMediaUrl;

@SerializedName(“updated_at”)

private String mUpdatedAt;

public String getCreatedAt() {

return mCreatedAt;

}

public void setCreatedAt(String createdAt) {

mCreatedAt = createdAt;

}

public String getId() {

return mId;

}

public void setId(String id) {

mId = id;

}

public String getMainTitle() {

return mMainTitle;

}

public void setMainTitle(String mainTitle) {

mMainTitle = mainTitle;

}

public String getMediaUrl() {

return mMediaUrl;

}

public void setMediaUrl(String mediaUrl) {

mMediaUrl = mediaUrl;

}

public String getUpdatedAt() {

return mUpdatedAt;

}

public void setUpdatedAt(String updatedAt) {

mUpdatedAt = updatedAt;

}

}

3. Modify the activity_main.xml and HorizontalSwipeRefreshLayout and RecyclerView

Let’s move to next step open activity_main.xml

and paste below code.

For better understanding of

HorizontalSwipeRefreshLayout read here.

4. For spacing between two items write a space divider

EqualSpacingItemDecoration is manage space between two view.

package com.wave.pagination.recyclerview.utils;

import android.graphics.Rect;

import android.support.v7.widget.GridLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.view.View;

public class EqualSpacingItemDecoration extends RecyclerView.ItemDecoration {

private final int spacing;

private int displayMode;

public static final int HORIZONTAL = 0;

public static final int VERTICAL = 1;

public static final int GRID = 2;

public EqualSpacingItemDecoration(int spacing) {

this(spacing, -1);

}

public EqualSpacingItemDecoration(int spacing, int displayMode) {

this.spacing = spacing;

this.displayMode = displayMode;

}

@Override

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

int position = parent.getChildViewHolder(view).getAdapterPosition();

int itemCount = state.getItemCount();

RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();

setSpacingForDirection(outRect, layoutManager, position, itemCount);

}

private void setSpacingForDirection(Rect outRect,

RecyclerView.LayoutManager layoutManager,

int position,

int itemCount) {

// Resolve display mode automatically

if (displayMode == -1) {

displayMode = resolveDisplayMode(layoutManager);

}

switch (displayMode) {

case HORIZONTAL:

outRect.left = spacing;

outRect.right = position == itemCount – 1 ? spacing : 0;

outRect.top = spacing;

outRect.bottom = spacing;

break;

case VERTICAL:

outRect.left = spacing;

outRect.right = spacing;

outRect.top = spacing;

outRect.bottom = position == itemCount – 1 ? spacing : 0;

break;

case GRID:

if (layoutManager instanceof GridLayoutManager) {

GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;

int cols = gridLayoutManager.getSpanCount();

int rows = itemCount / cols;

outRect.left = spacing;

outRect.right = position % cols == cols – 1 ? spacing : 0;

outRect.top = spacing;

outRect.bottom = position / cols == rows – 1 ? spacing : 0;

}

break;

}

}

private int resolveDisplayMode(RecyclerView.LayoutManager layoutManager) {

if (layoutManager instanceof GridLayoutManager) return GRID;

if (layoutManager.canScrollHorizontally()) return HORIZONTAL;

return VERTICAL;

}

}

5. Prepare Retrofit client for REST API calls

5.1 Create Retrofit API Service interface

package com.wave.pagination.recyclerview;

import com.wave.pagination.recyclerview.model.NewsItem;

import java.util.List;

import retrofit2.Call;

import retrofit2.http.GET;

import retrofit2.http.Query;

public interface RestApiService {

@GET(“newsfeed.php”)

Call> getNewsFeed(@Query(“page_no”) Integer pageNo);

}

5.2 Prepare Retrofit client for API calling

package com.wave.pagination.recyclerview;

import retrofit2.Retrofit;

import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitInstance {

private static final String BASE_URL = “https://androidwave.com/api/”;

private static Retrofit retrofit = null;

public static RestApiService getApiService() {

if (retrofit == null) {

retrofit = new Retrofit

.Builder()

.baseUrl(BASE_URL)

.addConverterFactory(GsonConverterFactory.create())

.build();

}

return retrofit.create(RestApiService.class);

}

}

6. Create a layout file for list item view

6.1 Create a layout file named is list_item for showing the news items.

6.2 Prepare view for loading view during API call

7. Writes a RecyclerView adapter for holding recycler item

In src folder create a new java class named is PaginationAdapter which extends RecyclerView.Adapter. than paste below code. In this adapter I’m using two views one for loading that will show when api call and second for showing list item

package com.wave.pagination.recyclerview;

import android.support.annotation.NonNull;

import android.support.v7.widget.RecyclerView;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ImageView;

import android.widget.TextView;

import com.wave.pagination.recyclerview.model.NewsItem;

import java.util.List;

public class PaginationAdapter extends RecyclerView.Adapter {

private static final int VIEW_TYPE_LOADING = 0;

public static final int VIEW_TYPE_NORMAL = 1;

private boolean isLoaderVisible = false;

private List mNewsItemList;

private Callback mCallback;

public PaginationAdapter(List news) {

this.mNewsItemList = news;

}

public void setCallback(Callback callback) {

mCallback = callback;

}

@NonNull

@Override

public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

switch (viewType) {

case VIEW_TYPE_NORMAL:

return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false));

case VIEW_TYPE_LOADING:

return new EmptyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, parent, false));

default:

return null;

}

}

@Override

public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {

holder.onBind(position);

}

@Override

public int getItemViewType(int position) {

if (isLoaderVisible) {

return position == mNewsItemList.size() – 1 ? VIEW_TYPE_LOADING : VIEW_TYPE_NORMAL;

} else {

return VIEW_TYPE_NORMAL;

}

}

@Override

public int getItemCount() {

return mNewsItemList == null ? 0 : mNewsItemList.size();

}

public void add(NewsItem response) {

mNewsItemList.add(response);

notifyItemInserted(mNewsItemList.size() – 1);

}

public void addAll(List postItems) {

for (NewsItem response : postItems) {

add(response);

}

}

private void remove(NewsItem postItems) {

int position = mNewsItemList.indexOf(postItems);

if (position > -1) {

mNewsItemList.remove(position);

notifyItemRemoved(position);

}

}

public void addLoading() {

isLoaderVisible = true;

add(new NewsItem());

}

public void removeLoading() {

isLoaderVisible = false;

int position = mNewsItemList.size() – 1;

NewsItem item = getItem(position);

if (item != null) {

mNewsItemList.remove(position);

notifyItemRemoved(position);

}

}

public void clear() {

while (getItemCount() > 0) {

remove(getItem(0));

}

}

NewsItem getItem(int position) {

return mNewsItemList.get(position);

}

public interface Callback {

void onRepoEmptyViewRetryClick();

}

public class ViewHolder extends BaseViewHolder {

TextView newTitle;

ImageView newsImage;

public ViewHolder(View itemView) {

super(itemView);

newTitle = itemView.findViewById(R.id.txtNewsTitle);

newsImage = itemView.findViewById(R.id.ivNewsImage);

}

protected void clear() {

}

public void onBind(int position) {

super.onBind(position);

NewsItem mNewsItem = mNewsItemList.get(position);

newTitle.setText(mNewsItem.getMainTitle());

//

Glide.with(itemView.getContext())

//

.load(mNewsItem.getMediaUrl()).apply(new RequestOptions().override(ScreenUtils.getScreenWidth(itemView.getContext()) – ViewUtils.dpToPx(36), 150).placeholder(R.drawable.picture).error(R.drawable.picture))

//

.into(newsImage);

}

}

public class EmptyViewHolder extends BaseViewHolder {

public EmptyViewHolder(View itemView) {

super(itemView);

}

@Override

protected void clear() {

}

}

}

8. Create Scroll listener

Create abstract class named PaginationScrollListener. With the help of PaginationScrollListener we will manageapagination

package com.wave.pagination.recyclerview.utils;

import android.support.v7.widget.LinearLayoutManager;

import android.support.v7.widget.RecyclerView;

public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {

LinearLayoutManager layoutManager;

private static final int PAGE_SIZE = 10;

/**

* Supporting only LinearLayoutManager for now.

*

* @param layoutManager

*/

public PaginationScrollListener(LinearLayoutManager layoutManager) {

this.layoutManager = layoutManager;

}

@Override

public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

super.onScrolled(recyclerView, dx, dy);

int visibleItemCount = layoutManager.getChildCount();

int totalItemCount = layoutManager.getItemCount();

int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();

if (!isLoading() && !isLastPage()) {

if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount

&& firstVisibleItemPosition >= 0

&& totalItemCount >= PAGE_SIZE) {

loadMoreItems();

}

}

}

protected abstract void loadMoreItems();

public abstract boolean isLastPage();

public abstract boolean isLoading();

}

9. Finally, Open the MainActivity and do following operation

package com.wave.pagination.recyclerview;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.support.v7.widget.LinearLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.util.Log;

import com.wave.pagination.recyclerview.model.NewsItem;

import com.wave.pagination.recyclerview.utils.EqualSpacingItemDecoration;

import com.wave.pagination.recyclerview.utils.PaginationScrollListener;

import com.wave.pagination.recyclerview.widget.HorizontalSwipeRefreshLayout;

import java.util.ArrayList;

import java.util.List;

import retrofit2.Call;

import retrofit2.Callback;

import retrofit2.Response;

public class MainActivity extends AppCompatActivity implements HorizontalSwipeRefreshLayout.OnRefreshListener {

private static final String TAG = “MainActivity”;

PaginationAdapter mPaginationAdapter;

LinearLayoutManager mLayoutManager;

RecyclerView mRecyclerView;

HorizontalSwipeRefreshLayout mSwipeRefreshLayout;

public static final int PAGE_START = 1;

private int currentPage = PAGE_START;

private boolean isLastPage = false;

private int totalPage = 3;

private boolean isLoading = false;

int itemCount = 0;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

getSupportActionBar().hide();

mRecyclerView = findViewById(R.id.mRecyclerView);

mSwipeRefreshLayout = findViewById(R.id.swipeRefresh);

mSwipeRefreshLayout.setOnRefreshListener(this);

mPaginationAdapter = new PaginationAdapter(new ArrayList());

mRecyclerView.setHasFixedSize(true);

mLayoutManager = new LinearLayoutManager(this);

mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

mRecyclerView.setLayoutManager(mLayoutManager);

mRecyclerView.addItemDecoration(new EqualSpacingItemDecoration(32, EqualSpacingItemDecoration.HORIZONTAL));

mRecyclerView.setAdapter(mPaginationAdapter);

mSwipeRefreshLayout.setRefreshing(true);

preparedListItem();

/**

* add scroll listener while user reach in bottom load more will call

*/

mRecyclerView.addOnScrollListener(new PaginationScrollListener(mLayoutManager) {

@Override

protected void loadMoreItems() {

isLoading = true;

currentPage++;

preparedListItem();

}

@Override

public boolean isLastPage() {

return isLastPage;

}

@Override

public boolean isLoading() {

return isLoading;

}

});

}

protected void preparedListItem() {

RestApiService apiService = RetrofitInstance.getApiService();

Call> call = apiService.getNewsFeed(currentPage);

Log.d(TAG, “loadItemFromServer: ” + currentPage);

call.enqueue(new Callback>() {

@Override

public void onResponse(Call> call, Response> response) {

if (currentPage != PAGE_START) mPaginationAdapter.removeLoading();

mPaginationAdapter.addAll(response.body());

mSwipeRefreshLayout.setRefreshing(false);

if (currentPage < totalPage) mPaginationAdapter.addLoading(); else isLastPage = true; isLoading = false; } @Override public void onFailure(Call> call, Throwable t) {

mSwipeRefreshLayout.setRefreshing(false);

}

});

}

@Override

public void onRefresh() {

itemCount = 0;

currentPage = PAGE_START;

isLastPage = false;

mPaginationAdapter.clear();

preparedListItem();

}

}

After following all the above step your app is ready to use, If you have any queries, feel free to ask them in the comment section below. I hope it’s helpful for you, then help me by sharing this post with all your friends who learning android app development. Happy Coding 🙂

Read More –

May 26, 2019

May 22, 2019

May 4, 2019

Leave a Reply

Your email address will not be published. Required fields are marked *