Last active
April 16, 2017 04:49
-
-
Save jt535/d61bec672736a4d80ef539d0492685b1 to your computer and use it in GitHub Desktop.
A Recycler View Item Decorator that adds sticky headers.
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.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