-
-
Save khaledkhj/2ae2e101b68a7f3590b87a90fd8f5c0c to your computer and use it in GitHub Desktop.
RecyclerView-Grid-with-Load-More
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by Vipul on 18/11/16. | |
*/ | |
public class Elements { | |
private int icon; | |
private String name; | |
public int getIcon() { | |
return icon; | |
} | |
public void setIcon(int icon) { | |
this.icon = icon; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 java.util.List; | |
/** | |
* Created by Vipul on 18/11/16. | |
*/ | |
public class ElementsAdapter extends RecyclerView.Adapter { | |
interface Callbacks { | |
public void onClickLoadMore(); | |
} | |
private Callbacks mCallbacks; | |
private static final int TYPE_HEADER = 0; | |
private static final int TYPE_ITEM = 1; | |
private static final int TYPE_FOOTER = 2; | |
private boolean mWithHeader = false; | |
private boolean mWithFooter = false; | |
private List<Elements> mFeedList; | |
public ElementsAdapter(List<Elements> feedList) { | |
this.mFeedList = feedList; | |
} | |
@Override | |
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |
View itemView = null; | |
if (viewType == TYPE_FOOTER) { | |
itemView = View.inflate(parent.getContext(), R.layout.row_loadmore, null); | |
return new LoadMoreViewHolder(itemView); | |
} else { | |
itemView = View.inflate(parent.getContext(), R.layout.row_element, null); | |
return new ElementsViewHolder(itemView); | |
} | |
} | |
@Override | |
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { | |
if(holder instanceof LoadMoreViewHolder) { | |
LoadMoreViewHolder loadMoreViewHolder = (LoadMoreViewHolder) holder; | |
loadMoreViewHolder.itemView.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View view) { | |
if(mCallbacks!=null) | |
mCallbacks.onClickLoadMore(); | |
} | |
}); | |
} else { | |
ElementsViewHolder elementsViewHolder = (ElementsViewHolder) holder; | |
Elements elements = mFeedList.get(position); | |
elementsViewHolder.icon.setImageResource(elements.getIcon()); | |
elementsViewHolder.name.setText(elements.getName()); | |
} | |
} | |
@Override | |
public int getItemCount() { | |
int itemCount = mFeedList.size(); | |
if (mWithHeader) | |
itemCount++; | |
if (mWithFooter) | |
itemCount++; | |
return itemCount; | |
} | |
@Override | |
public int getItemViewType(int position) { | |
if (mWithHeader && isPositionHeader(position)) | |
return TYPE_HEADER; | |
if (mWithFooter && isPositionFooter(position)) | |
return TYPE_FOOTER; | |
return TYPE_ITEM; | |
} | |
public boolean isPositionHeader(int position) { | |
return position == 0 && mWithHeader; | |
} | |
public boolean isPositionFooter(int position) { | |
return position == getItemCount() - 1 && mWithFooter; | |
} | |
public void setWithHeader(boolean value){ | |
mWithHeader = value; | |
} | |
public void setWithFooter(boolean value){ | |
mWithFooter = value; | |
} | |
public void setCallback(Callbacks callbacks){ | |
mCallbacks = callbacks; | |
} | |
public class ElementsViewHolder extends RecyclerView.ViewHolder { | |
private ImageView icon; | |
private TextView name; | |
public ElementsViewHolder(View itemView) { | |
super(itemView); | |
icon = (ImageView) itemView.findViewById(R.id.icon); | |
name = (TextView) itemView.findViewById(R.id.name); | |
} | |
} | |
public class LoadMoreViewHolder extends RecyclerView.ViewHolder { | |
public LoadMoreViewHolder(View itemView) { | |
super(itemView); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.content.res.TypedArray; | |
import android.graphics.Canvas; | |
import android.graphics.Rect; | |
import android.graphics.drawable.Drawable; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.View; | |
/** | |
* ItemDecoration implementation that applies and inset margin | |
* around each child of the RecyclerView. It also draws item dividers | |
* that are expected from a vertical list implementation, such as | |
* ListView. | |
*/ | |
public class GridDividerDecoration extends RecyclerView.ItemDecoration { | |
private static final int[] ATTRS = { android.R.attr.listDivider }; | |
private Drawable mDivider; | |
private int mInsets; | |
public GridDividerDecoration(Context context) { | |
TypedArray a = context.obtainStyledAttributes(ATTRS); | |
mDivider = a.getDrawable(0); | |
a.recycle(); | |
mInsets = 1; | |
} | |
@Override | |
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { | |
drawVertical(c, parent); | |
drawHorizontal(c, parent); | |
} | |
/** Draw dividers at each expected grid interval */ | |
public void drawVertical(Canvas c, RecyclerView parent) { | |
if (parent.getChildCount() == 0) return; | |
final int childCount = parent.getChildCount(); | |
for (int i = 0; i < childCount; i++) { | |
final View child = parent.getChildAt(i); | |
final RecyclerView.LayoutParams params = | |
(RecyclerView.LayoutParams) child.getLayoutParams(); | |
final int left = child.getLeft() - params.leftMargin - mInsets; | |
final int right = child.getRight() + params.rightMargin + mInsets; | |
final int top = child.getBottom() + params.bottomMargin + mInsets; | |
final int bottom = top + mDivider.getIntrinsicHeight(); | |
mDivider.setBounds(left, top, right, bottom); | |
mDivider.draw(c); | |
} | |
} | |
/** Draw dividers to the right of each child view */ | |
public void drawHorizontal(Canvas c, RecyclerView parent) { | |
final int childCount = parent.getChildCount(); | |
for (int i = 0; i < childCount; i++) { | |
final View child = parent.getChildAt(i); | |
final RecyclerView.LayoutParams params = | |
(RecyclerView.LayoutParams) child.getLayoutParams(); | |
final int left = child.getRight() + params.rightMargin + mInsets; | |
final int right = left + mDivider.getIntrinsicWidth(); | |
final int top = child.getTop() - params.topMargin - mInsets; | |
final int bottom = child.getBottom() + params.bottomMargin + mInsets; | |
mDivider.setBounds(left, top, right, bottom); | |
mDivider.draw(c); | |
} | |
} | |
@Override | |
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { | |
//We can supply forced insets for each item view here in the Rect | |
outRect.set(mInsets, mInsets, mInsets, mInsets); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.Bundle; | |
import android.support.v7.app.AppCompatActivity; | |
import android.support.v7.widget.GridLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.support.v7.widget.Toolbar; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class MainActivity extends AppCompatActivity implements ElementsAdapter.Callbacks{ | |
private List<Elements> mainList = new ArrayList<>(); | |
private List<Elements> dummyList = new ArrayList<>(); | |
private RecyclerView recyclerView; | |
private ElementsAdapter elementsAdapter; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); | |
setSupportActionBar(toolbar); | |
recyclerView = (RecyclerView) findViewById(R.id.recyclerView); | |
int columns = 2; | |
final GridLayoutManager gridLayoutManager = new GridLayoutManager(this, columns); | |
recyclerView.addItemDecoration(new GridDividerDecoration(this)); | |
recyclerView.setLayoutManager(gridLayoutManager); | |
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { | |
@Override | |
public int getSpanSize(int position) { | |
return elementsAdapter.isPositionFooter(position) ? gridLayoutManager.getSpanCount() : 1; | |
} | |
}); | |
// added all elements to main list | |
for(int i = 0; i<12; ++i) { | |
Elements elements = new Elements(); | |
elements.setIcon(R.mipmap.ic_launcher); | |
elements.setName("Element "+i); | |
mainList.add(elements); | |
} | |
// now only add number of elements for the first show i.e. 6 | |
for(int i = 0; i<6; ++i) { | |
dummyList.add(mainList.get(i)); | |
} | |
elementsAdapter = new ElementsAdapter(dummyList); | |
elementsAdapter.setCallback(this); | |
elementsAdapter.setWithFooter(true); //enabling footer to show | |
recyclerView.setAdapter(elementsAdapter); | |
} | |
@Override | |
public void onClickLoadMore() { | |
elementsAdapter.setWithFooter(false); // hide footer | |
// now add remaining elements | |
for(int i = 6; i<mainList.size(); ++i) { | |
dummyList.add(mainList.get(i)); | |
} | |
elementsAdapter.notifyDataSetChanged(); // more elements will be added | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
android:orientation="vertical" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:padding="25dp" | |
android:background="@android:color/white" | |
android:gravity="center"> | |
<ImageView | |
android:layout_width="50dp" | |
android:layout_height="50dp" | |
android:id="@+id/icon"/> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="10dp" | |
android:id="@+id/name" /> | |
</LinearLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
android:orientation="vertical" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:background="@android:color/white" | |
android:gravity="center"> | |
<TextView | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:gravity="center" | |
android:padding="15dp" | |
android:text="Load More" | |
android:textSize="16sp" | |
android:textColor="#FF5722"/> | |
</LinearLayout> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment