Custom Recycler view demo.
Add the gradle dependency to your app build.gradle file
compile 'com.android.support:recyclerview-v7:25.3.1'
Demo
Models class
import java.util.ArrayList;
import java.util.List;
public class Getdata {
public List<Data> data = new ArrayList<>();
public Pagination pagination = new Pagination();
public Meta meta = new Meta();
public class Meta {
public String status;
public String msg;
}
public class Pagination {
public String count;
}
public class Data {
public Images images = new Images();
public String username;
public class Images {
public Fixed_width_small_still fixed_width_small_still = new Fixed_width_small_still();
public FixedHeight fixed_height = new FixedHeight();
public Preview_gif preview_gif = new Preview_gif();
public class Preview_gif {
public String url;
}
public class FixedHeight{
public String url;
public String width;
public String height;
}
public class Fixed_width_small_still {
public String url;
public String width;
public String height;
}
}
}
}
StaggeredGridLayoutActivity.java
public class StaggeredGridLayoutActivity extends AppCompatActivity {
private ProgressDialogFragment progressDialogFragment;
StaggeredGridLayutAdapter mAdapter;
@BindView(R.id.recycler_view)
RecyclerView recycler_view;
private EndlessRecyclerViewScrollListener endlessscrollListener;
public int page = 0;
private StaggeredGridLayoutManager staggeredGridLayoutManager;
ArrayList<Getdata.Data> getDataArray;
Getdata getdatas;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_staggeredgridlayout);
ButterKnife.bind(this);
getDataArray = new ArrayList<>();
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.HORIZONTAL);
staggeredGridLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
// staggeredGridLayoutManager.invalidateSpanAssignments();
recycler_view.setLayoutManager(staggeredGridLayoutManager);
mAdapter = new StaggeredGridLayutAdapter(this, getDataArray);
recycler_view.setAdapter(mAdapter);
endlessscrollListener = new EndlessRecyclerViewScrollListener(staggeredGridLayoutManager) {
@Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
Log.e("Page==", page + "" + " total==" + totalItemsCount);
loadMore(getDataArray.size() + 1);
}
};
recycler_view.addOnScrollListener(endlessscrollListener);
getData(page);
}
private void getData(int page) {
showProgressDailog("Please Wait");
WebserviceApi webserviceApi = ServiceGenerator.createService(WebserviceApi.class);
Call<Getdata> getdataCall = webserviceApi.getGifDatas("dc6zaTOxFJmzC", page + "");
getdataCall.enqueue(new Callback<Getdata>() {
@Override
public void onResponse(Call<Getdata> call, Response<Getdata> response) {
hideProgressDialog();
Log.e("getData success", "getData success");
getdatas = response.body();
if (getDataArray != null) {
getDataArray.addAll(getdatas.data);
mAdapter.notifyDataChanged();
}
}
@Override
public void onFailure(Call<Getdata> call, Throwable t) {
hideProgressDialog();
Log.e("Fail", "fail");
}
});
}
public void loadMore(int page) {
WebserviceApi webserviceApi = ServiceGenerator.createService(WebserviceApi.class);
Call<Getdata> getdataCall = webserviceApi.getGifDatas("dc6zaTOxFJmzC", page + "");
getdataCall.enqueue(new Callback<Getdata>() {
@Override
public void onResponse(Call<Getdata> call, Response<Getdata> response) {
Log.e("loadMore success", "loadMore success");
getdatas = response.body();
if (getDataArray.size() > 0) {
if (getDataArray != null) {
getDataArray.addAll(getdatas.data);
mAdapter.notifyDataChanged();
} else {
Toast.makeText(StaggeredGridLayoutActivity.this, "No More Data Available", Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onFailure(Call<Getdata> call, Throwable t) {
Log.e("Fail", "fail");
}
});
}
public void showProgressDailog(String message) {
progressDialogFragment = new ProgressDialogFragment(message);
progressDialogFragment.show(getFragmentManager(), "");
progressDialogFragment.setCancelable(false);
}
public void hideProgressDialog() {
try {
if (progressDialogFragment != null) {
progressDialogFragment.dismiss();
}
} catch (Exception e) {
}
}
}
EndlessRecyclerViewScrollListener.java
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
RecyclerView.LayoutManager mLayoutManager;
public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
}
public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}
public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}
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;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScrolled(RecyclerView view, int dx, int dy) {
int lastVisibleItemPosition = 0;
int totalItemCount = mLayoutManager.getItemCount();
if (mLayoutManager instanceof StaggeredGridLayoutManager) {
int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
// get maximum element within the list
lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
} else if (mLayoutManager instanceof GridLayoutManager) {
lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
} else if (mLayoutManager instanceof LinearLayoutManager) {
lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
}
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) {
this.loading = true;
}
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
currentPage++;
onLoadMore(currentPage, totalItemCount, view);
loading = true;
}
}
// Call this method whenever performing new searches
public void resetState() {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = 0;
this.loading = true;
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);
}
StaggeredGridLayutAdapter.java
public class StaggeredGridLayutAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context mContext;
boolean isLoading = false, isMoreDataAvailable = true;
ArrayList<Getdata.Data> getDataArray;
public StaggeredGridLayutAdapter(Context context, ArrayList<Getdata.Data> dataList) {
getDataArray = dataList;
mContext = context;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.staggered_list_item, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//if (holder instanceof MyViewHolder) {
MyViewHolder myViewHolder = (MyViewHolder) holder;
Getdata.Data data = getDataArray.get(position);
myViewHolder.country_name.setText(data.username);
Glide.with(mContext).load(data.images.fixed_height.url).placeholder(R.drawable.ic_launcher).diskCacheStrategy(DiskCacheStrategy.ALL).crossFade().
into(((MyViewHolder) holder).country_photo);
}
@Override
public int getItemCount() {
return getDataArray == null ? 0 : getDataArray.size();
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public ImageView country_photo;
public TextView country_name;
// GifImageView gifImageView;
public MyViewHolder(View itemView) {
super(itemView);
// gifImageView = (GifImageView) itemView.findViewById(R.id.gifimgView);
country_photo = (ImageView) itemView.findViewById(R.id.country_photo);
country_name = (TextView) itemView.findViewById(R.id.country_name);
}
}
}
activity_staggeredgridlayout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
<!--<android.support.v4.widget.SwipeRefreshLayout-->
<!--android:id="@+id/swipe_container"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent">-->
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="horizontal" />
<!--</android.support.v4.widget.SwipeRefreshLayout>-->
</LinearLayout>
staggered_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="3dp">
<ImageView
android:id="@+id/country_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY" />
<TextView
android:id="@+id/country_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#1976D2"
android:gravity="center_horizontal"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:text="@string/hello_world"
android:textColor="#ffffff"
android:textSize="12dp"
android:visibility="gone" />
</LinearLayout>
</RelativeLayout>