Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@chanakin
Created June 1, 2016 21:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chanakin/947f5eb5eed4fc9af3f3221f48964308 to your computer and use it in GitHub Desktop.
Save chanakin/947f5eb5eed4fc9af3f3221f48964308 to your computer and use it in GitHub Desktop.
package com.yourpackage.android;
import android.content.Context;
import android.support.annotation.CallSuper;
import android.support.annotation.IdRes;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.yourpackage.android.R;
import java.util.ArrayList;
/**
* Handles putting headers and footers on a recyclerview
*/
public abstract class BaseRecyclerViewAdapter<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
LayoutInflater inflater;
private final ArrayList<View> headerViews;
private final ArrayList<View> footerViews;
private boolean headerShouldSpanView = true;
private boolean footerShouldSpanView = true;
private final int headerViewType;
private final int footerViewType;
@CallSuper
public void addHeaderView(View headerView) {
this.headerViews.add(headerView);
}
@CallSuper
void removeHeaderView(View headerView) {
this.headerViews.remove(headerView);
}
@CallSuper
public void addFooterView(View footerView) {
this.footerViews.add(footerView);
}
@CallSuper
void removeFooterView(View footerView) {
this.footerViews.remove(footerView);
}
private boolean isListHeaderPosition(int position) {
return position < headerViews.size();
}
private boolean isListFooterPosition(int position) {
return position >= getListItemCount() + headerViews.size();
}
/**
* @param context - activity context
* @param headerViewType -- must be UNIQUE; used to identify a header view
* @param footerViewType -- must be UNIQUE; used to identify a footer view
*/
protected BaseRecyclerViewAdapter(Context context, @IdRes int headerViewType, @IdRes int footerViewType) {
super();
inflater = LayoutInflater.from(context);
this.headerViewType = headerViewType;
this.footerViewType = footerViewType;
headerViews = new ArrayList<>();
footerViews = new ArrayList<>();
}
public static class FixedViewHolder extends RecyclerView.ViewHolder {
public final FrameLayout frameLayout;
public FixedViewHolder(FrameLayout view) {
super(view);
frameLayout = view;
}
}
@Override
public final int getItemViewType(int position) {
if (isListHeaderPosition(position)) {
return headerViewType;
}
if (isListFooterPosition(position)) {
return footerViewType;
}
return getListItemViewType(convertAdapterPositionToUnderlyingListDataPosition(position));
}
@Override
public final int getItemCount() {
return headerViews.size() + footerViews.size() + getListItemCount();
}
@Override
public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) {
if (typeView == headerViewType || typeView == footerViewType) {
final FrameLayout headerContainer = (FrameLayout) inflater.inflate(R.layout.empty_container, parent, false);
return new FixedViewHolder(headerContainer);
}
return onCreateListItemViewHolder(parent, typeView);
}
public int convertAdapterPositionToUnderlyingListDataPosition(int position) {
return position - headerViews.size();
}
int convertUnderlyingListDataPositionToAdapterPosition(int position) {
return position + headerViews.size();
}
@Override
public final void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (viewHolder instanceof FixedViewHolder) {
if (isListHeaderPosition(position)) {
bindNonItemView((FixedViewHolder) viewHolder, headerViews.get(position), headerShouldSpanView);
return;
}
if (isListFooterPosition(position)) {
bindNonItemView((FixedViewHolder) viewHolder, footerViews.get(getFooterIndex(position)), footerShouldSpanView);
return;
}
return;
}
//noinspection unchecked
onBindListItemViewHolder((T) viewHolder, convertAdapterPositionToUnderlyingListDataPosition(position));
}
private void bindNonItemView(FixedViewHolder viewHolder, View view, boolean shouldSpanView) {
if (viewHolder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams && shouldSpanView) {
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams();
layoutParams.setFullSpan(true);
}
if (viewHolder.frameLayout.getChildCount() > 0) {
viewHolder.frameLayout.removeAllViews();
}
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null) {
parent.removeView(view);
}
viewHolder.frameLayout.addView(view);
if (viewHolder.frameLayout.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams && shouldSpanView) {
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewHolder.frameLayout.getLayoutParams();
layoutParams.setFullSpan(true);
viewHolder.frameLayout.setLayoutParams(layoutParams);
}
}
private int getFooterIndex(int position) {
return position - getListItemCount() - headerViews.size();
}
@Override
public final long getItemId(int position) {
if (isListHeaderPosition(position) || isListFooterPosition(position)) {
return -1;
}
return getListItemId(convertAdapterPositionToUnderlyingListDataPosition(position));
}
protected abstract RecyclerView.ViewHolder onCreateListItemViewHolder(ViewGroup parent, int typeView);
protected abstract void onBindListItemViewHolder(T viewHolder, int position);
protected abstract int getListItemCount();
@IdRes
protected abstract int getListItemViewType(int position);
protected abstract long getListItemId(int position);
public int getHeaderCount() {
return headerViews != null ? headerViews.size() : 0;
}
public int getFooterCount() {
return footerViews != null ? footerViews.size() : 0;
}
public void setHeaderShouldSpanView(boolean headerShouldSpanView) {
this.headerShouldSpanView = headerShouldSpanView;
if (headerViews.size() > 0) {
notifyItemRangeChanged(0, headerViews.size() - 1);
}
}
public void setFooterShouldSpanView(boolean footerShouldSpanView) {
this.footerShouldSpanView = footerShouldSpanView;
if (footerViews.size() > 0) {
notifyItemRangeChanged(getItemCount() - footerViews.size() - 1, getItemCount() - 1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment