Skip to content

Instantly share code, notes, and snippets.

@jt535
Last active April 16, 2017 04:49
Show Gist options
  • Save jt535/d61bec672736a4d80ef539d0492685b1 to your computer and use it in GitHub Desktop.
Save jt535/d61bec672736a4d80ef539d0492685b1 to your computer and use it in GitHub Desktop.
A Recycler View Item Decorator that adds sticky headers.
import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public abstract class StickHeaderItemDecorator extends RecyclerView.ItemDecoration {
/* Make your view holder implement this interface */
public interface HeaderRelationship {
/* Return true if this object is located directly after a header */
public boolean isDirectlyAfterHeader();
}
private int headerHeight;
public StickHeaderItemDecorator(int headerHeight) {
this.headerHeight = headerHeight;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(0, 0, 0, 0);
RecyclerView.ViewHolder viewHolder = parent.getChildViewHolder(view);
if (isDirectlyAfterHeader(viewHolder)) {
outRect.top = headerHeight;
}
}
private boolean isDirectlyAfterHeader(RecyclerView.ViewHolder viewHolder) {
return viewHolder != null
&& viewHolder instanceof HeaderRelationship
&& ((HeaderRelationship) viewHolder).isDirectlyAfterHeader();
}
/* Draw your sticky header inside of "headerBounds" using the "viewHolder." */
protected abstract void drawHeader(Canvas c, RecyclerView parent, RecyclerView.State state, Rect headerBounds, RecyclerView.ViewHolder viewHolder);
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
Rect headerBounds = new Rect();
int highestHeaderTop = Integer.MAX_VALUE;
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
if(childCount == 0) return;
for (int i = 0; i < childCount; ++i) {
View view = parent.getChildAt(i);
RecyclerView.ViewHolder viewHolder = parent.getChildViewHolder(view);
if (!isDirectlyAfterHeader(viewHolder)) continue;
int bottom = view.getTop();
int top = bottom - headerHeight;
if (top <= 0) continue;
highestHeaderTop = Math.min(top, highestHeaderTop);
headerBounds.set(left, top, right, bottom);
drawHeader(c, parent, state, headerBounds, viewHolder);
}
int headerTop = highestHeaderTop > headerHeight ? 0 : highestHeaderTop - headerHeight;
int headerBottom = headerTop + headerHeight;
RecyclerView.ViewHolder viewHolder = parent.getChildViewHolder(parent.getChildAt(0));
headerBounds.set(left, headerTop, right, headerBottom);
drawHeader(c, parent, state, headerBounds, viewHolder);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment