You can use this class to realize a simple sectioned grid RecyclerView.Adapter without changing your code. The RecyclerView has to use a GridLayoutManager.android
This is a porting of the class SimpleSectionedListAdapter provided by Googleios
If you are looking for a sectioned list RecyclerView.Adapter you can take a look heregit
Example:github
//Your RecyclerView mRecyclerView = (RecyclerView) getActivity().findViewById(R.id.list); mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(),4)); //Your RecyclerView.Adapter mAdapter = new SimpleAdapter(getActivity()); //This is the code to provide a sectioned grid List<SectionedGridRecyclerViewAdapter.Section> sections = new ArrayList<SectionedGridRecyclerViewAdapter.Section>(); //Sections sections.add(new SectionedGridRecyclerViewAdapter.Section(0,"Section 1")); sections.add(new SectionedGridRecyclerViewAdapter.Section(5,"Section 2")); sections.add(new SectionedGridRecyclerViewAdapter.Section(12,"Section 3")); sections.add(new SectionedGridRecyclerViewAdapter.Section(14,"Section 4")); sections.add(new SectionedGridRecyclerViewAdapter.Section(20,"Section 5")); //Add your adapter to the sectionAdapter SectionedGridRecyclerViewAdapter.Section[] dummy = new SectionedGridRecyclerViewAdapter.Section[sections.size()]; SectionedGridRecyclerViewAdapter mSectionedAdapter = new SectionedGridRecyclerViewAdapter(getActivity(),R.layout.section,R.id.section_text,mRecyclerView,mAdapter); mSectionedAdapter.setSections(sections.toArray(dummy)); //Apply this adapter to the RecyclerView mRecyclerView.setAdapter(mSectionedAdapter);
You can customize the section layout, changing the layout section.xml
and changing the code in the SectionedGridRecyclerViewAdapter.SectionViewHolder
class and SectionedGridRecyclerViewAdapter#onBindViewHolder
method.c#
item.xmlapp
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/title" android:layout_width="match_parent" android:layout_height="130dp" android:gravity="center" android:layout_margin="4dp" android:textColor="#999999" android:textStyle="bold" android:textSize="22sp" android:background="@drawable/item_background"/>
section.xmlide
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="48dp" android:gravity="center_vertical" android:paddingLeft="16dp" android:singleLine="true" android:textAllCaps="true" android:background="#90CAF9" android:textSize="16sp" android:id="@+id/section_text" android:textStyle="bold" />
SectionedGridRecyclerViewAdapter.javaui
/** * @author Gabriele Mariotti (gabri.mariotti@gmail.com) */ public class SectionedGridRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final Context mContext; private static final int SECTION_TYPE = 0; private boolean mValid = true; private int mSectionResourceId; private int mTextResourceId; private LayoutInflater mLayoutInflater; private RecyclerView.Adapter mBaseAdapter; private SparseArray<Section> mSections = new SparseArray<Section>(); private RecyclerView mRecyclerView; public SectionedGridRecyclerViewAdapter(Context context, int sectionResourceId, int textResourceId,RecyclerView recyclerView, RecyclerView.Adapter baseAdapter) { mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mSectionResourceId = sectionResourceId; mTextResourceId = textResourceId; mBaseAdapter = baseAdapter; mContext = context; mRecyclerView = recyclerView; mBaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { @Override public void onChanged() { mValid = mBaseAdapter.getItemCount()>0; notifyDataSetChanged(); } @Override public void onItemRangeChanged(int positionStart, int itemCount) { mValid = mBaseAdapter.getItemCount()>0; notifyItemRangeChanged(positionStart, itemCount); } @Override public void onItemRangeInserted(int positionStart, int itemCount) { mValid = mBaseAdapter.getItemCount()>0; notifyItemRangeInserted(positionStart, itemCount); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { mValid = mBaseAdapter.getItemCount()>0; notifyItemRangeRemoved(positionStart, itemCount); } }); final GridLayoutManager layoutManager = (GridLayoutManager)(mRecyclerView.getLayoutManager()); layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return (isSectionHeaderPosition(position))? layoutManager.getSpanCount() : 1 ; } }); } public static class SectionViewHolder extends RecyclerView.ViewHolder { public TextView title; public SectionViewHolder(View view,int mTextResourceid) { super(view); title = (TextView) view.findViewById(mTextResourceid); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) { if (typeView == SECTION_TYPE) { final View view = LayoutInflater.from(mContext).inflate(mSectionResourceId, parent, false); return new SectionViewHolder(view,mTextResourceId); }else{ return mBaseAdapter.onCreateViewHolder(parent, typeView -1); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) { if (isSectionHeaderPosition(position)) { ((SectionViewHolder)sectionViewHolder).title.setText(mSections.get(position).title); }else{ mBaseAdapter.onBindViewHolder(sectionViewHolder,sectionedPositionToPosition(position)); } } @Override public int getItemViewType(int position) { return isSectionHeaderPosition(position) ? SECTION_TYPE : mBaseAdapter.getItemViewType(sectionedPositionToPosition(position)) +1 ; } public static class Section { int firstPosition; int sectionedPosition; CharSequence title; public Section(int firstPosition, CharSequence title) { this.firstPosition = firstPosition; this.title = title; } public CharSequence getTitle() { return title; } } public void setSections(Section[] sections) { mSections.clear(); Arrays.sort(sections, new Comparator<Section>() { @Override public int compare(Section o, Section o1) { return (o.firstPosition == o1.firstPosition) ? 0 : ((o.firstPosition < o1.firstPosition) ? -1 : 1); } }); int offset = 0; // offset positions for the headers we're adding for (Section section : sections) { section.sectionedPosition = section.firstPosition + offset; mSections.append(section.sectionedPosition, section); ++offset; } notifyDataSetChanged(); } public int positionToSectionedPosition(int position) { int offset = 0; for (int i = 0; i < mSections.size(); i++) { if (mSections.valueAt(i).firstPosition > position) { break; } ++offset; } return position + offset; } public int sectionedPositionToPosition(int sectionedPosition) { if (isSectionHeaderPosition(sectionedPosition)) { return RecyclerView.NO_POSITION; } int offset = 0; for (int i = 0; i < mSections.size(); i++) { if (mSections.valueAt(i).sectionedPosition > sectionedPosition) { break; } --offset; } return sectionedPosition + offset; } public boolean isSectionHeaderPosition(int position) { return mSections.get(position) != null; } @Override public long getItemId(int position) { return isSectionHeaderPosition(position) ? Integer.MAX_VALUE - mSections.indexOfKey(position) : mBaseAdapter.getItemId(sectionedPositionToPosition(position)); } @Override public int getItemCount() { return (mValid ? mBaseAdapter.getItemCount() + mSections.size() : 0); } }
SimpleAdapter.javathis
/** * @author Gabriele Mariotti (gabri.mariotti@gmail.com) */ public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.SimpleViewHolder> { private static final int COUNT = 100; private final Context mContext; private final List<Integer> mItems; private int mCurrentItemId = 0; public static class SimpleViewHolder extends RecyclerView.ViewHolder { public final TextView title; public SimpleViewHolder(View view) { super(view); title = (TextView) view.findViewById(R.id.title); } } public SimpleAdapter(Context context) { mContext = context; mItems = new ArrayList<Integer>(COUNT); for (int i = 0; i < COUNT; i++) { addItem(i); } } public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final View view = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false); return new SimpleViewHolder(view); } @Override public void onBindViewHolder(SimpleViewHolder holder, final int position) { holder.title.setText(mItems.get(position).toString()); } public void addItem(int position) { final int id = mCurrentItemId++; mItems.add(position, id); notifyItemInserted(position); } public void removeItem(int position) { mItems.remove(position); notifyItemRemoved(position); } @Override public int getItemCount() { return mItems.size(); } }