package licola.demo.com.huabandemo.Widget.MyRecyclerview; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; /** * Created by cundong on 2015/10/9. * <p/> * RecyclerView.Adapter with Header and Footer */ public class HeaderAndFooterRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final int TYPE_HEADER_VIEW = Integer.MIN_VALUE; private static final int TYPE_FOOTER_VIEW = Integer.MIN_VALUE + 1; /** * RecyclerView使用的,真正的Adapter */ private RecyclerView.Adapter<RecyclerView.ViewHolder> mInnerAdapter; private ArrayList<View> mHeaderViews = new ArrayList<>(); private ArrayList<View> mFooterViews = new ArrayList<>(); private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() { @Override public void onChanged() { super.onChanged(); notifyDataSetChanged(); } @Override public void onItemRangeChanged(int positionStart, int itemCount) { super.onItemRangeChanged(positionStart, itemCount); notifyItemRangeChanged(positionStart + getHeaderViewsCount(), itemCount); } @Override public void onItemRangeInserted(int positionStart, int itemCount) { super.onItemRangeInserted(positionStart, itemCount); notifyItemRangeInserted(positionStart + getHeaderViewsCount(), itemCount); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { super.onItemRangeRemoved(positionStart, itemCount); notifyItemRangeRemoved(positionStart + getHeaderViewsCount(), itemCount); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { super.onItemRangeMoved(fromPosition, toPosition, itemCount); int headerViewsCountCount = getHeaderViewsCount(); notifyItemRangeChanged(fromPosition + headerViewsCountCount, toPosition + headerViewsCountCount + itemCount); } }; public HeaderAndFooterRecyclerViewAdapter() { } public HeaderAndFooterRecyclerViewAdapter(RecyclerView.Adapter innerAdapter) { setAdapter(innerAdapter); } /** * 设置adapter * @param adapter */ public void setAdapter(RecyclerView.Adapter<RecyclerView.ViewHolder> adapter) { if (adapter != null) { if (!(adapter instanceof RecyclerView.Adapter)) throw new RuntimeException("your adapter must be a RecyclerView.Adapter"); } if (mInnerAdapter != null) { notifyItemRangeRemoved(getHeaderViewsCount(), mInnerAdapter.getItemCount()); mInnerAdapter.unregisterAdapterDataObserver(mDataObserver); } this.mInnerAdapter = adapter; mInnerAdapter.registerAdapterDataObserver(mDataObserver); notifyItemRangeInserted(getHeaderViewsCount(), mInnerAdapter.getItemCount()); } public RecyclerView.Adapter getInnerAdapter() { return mInnerAdapter; } public void addHeaderView(View header) { if (header == null) { throw new RuntimeException("header is null"); } mHeaderViews.add(header); this.notifyDataSetChanged(); } public void addFooterView(View footer) { if (footer == null) { throw new RuntimeException("footer is null"); } mFooterViews.add(footer); this.notifyDataSetChanged(); } /** * 返回第一个FoView * @return */ public View getFooterView() { return getFooterViewsCount()>0 ? mFooterViews.get(0) : null; } /** * 返回第一个HeaderView * @return */ public View getHeaderView() { return getHeaderViewsCount()>0 ? mHeaderViews.get(0) : null; } public void removeHeaderView(View view) { mHeaderViews.remove(view); this.notifyDataSetChanged(); } public void removeFooterView(View view) { mFooterViews.remove(view); this.notifyDataSetChanged(); } public int getHeaderViewsCount() { return mHeaderViews.size(); } public int getFooterViewsCount() { return mFooterViews.size(); } public boolean isHeader(int position) { return getHeaderViewsCount() > 0 && position == 0; } public boolean isFooter(int position) { int lastPosition = getItemCount() - 1; return getFooterViewsCount() > 0 && position == lastPosition; } /** * 根据 viewType 和 headerViewsCountCount 的数量 * 决定创建的 ViewHolder是 使用List<View> mHeaderViews 还是内部adapter的 onCreateViewHolder * @param parent * @param viewType * @return */ @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { int headerViewsCountCount = getHeaderViewsCount(); if (viewType < TYPE_HEADER_VIEW + headerViewsCountCount) { return new ViewHolder(mHeaderViews.get(viewType - TYPE_HEADER_VIEW)); } else if (viewType >= TYPE_FOOTER_VIEW && viewType < Integer.MAX_VALUE / 2) { return new ViewHolder(mFooterViews.get(viewType - TYPE_FOOTER_VIEW)); } else { return mInnerAdapter.onCreateViewHolder(parent, viewType - Integer.MAX_VALUE / 2); } } @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { super.onViewAttachedToWindow(holder); //添加代码 需要调用内部adapter 才能收到通知 mInnerAdapter.onViewAttachedToWindow(holder); } @Override public void onViewRecycled(RecyclerView.ViewHolder holder) { super.onViewRecycled(holder); //添加代码 需要调用内部adapter 才能收到通知 mInnerAdapter.onViewRecycled(holder); } /** * head和foot的视图不复用 不需要特别的 onBindViewHolder * 只是在 使用StaggeredGridLayoutManager 瀑布流时候 让head和foot 视图占据满格 setFullSpan(true) * @param holder * @param position */ @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int headerViewsCountCount = getHeaderViewsCount(); if (position >= headerViewsCountCount && position < headerViewsCountCount + mInnerAdapter.getItemCount()) { mInnerAdapter.onBindViewHolder(holder, position - headerViewsCountCount); } else { ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); if(layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) { ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true); } } } @Override public int getItemCount() { return getHeaderViewsCount() + getFooterViewsCount() + mInnerAdapter.getItemCount(); } @Override public int getItemViewType(int position) { int innerCount = mInnerAdapter.getItemCount(); int headerViewsCountCount = getHeaderViewsCount(); if (position < headerViewsCountCount) { return TYPE_HEADER_VIEW + position; } else if (headerViewsCountCount <= position && position < headerViewsCountCount + innerCount) { int innerItemViewType = mInnerAdapter.getItemViewType(position - headerViewsCountCount); if(innerItemViewType >= Integer.MAX_VALUE / 2) { throw new IllegalArgumentException("your adapter's return value of getViewTypeCount() must < Integer.MAX_VALUE / 2"); } return innerItemViewType + Integer.MAX_VALUE / 2; } else { return TYPE_FOOTER_VIEW + position - headerViewsCountCount - innerCount; } } public class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(View itemView) { super(itemView); } } }