RecyclerView: adds the head and tail la S, and recyclerview tails
RecyclerView has been available for a long time. I believe you are familiar with it. If you have used it, you may find that RecyclerView cannot add headerView and footView, this makes us feel a little painful. Maybe you will say, it's okay. We can rewrite the getItemViewType (int position) method to implement multiple la S. The specific implementation is as follows:
@Override public int getItemViewType(int position) { if (position == 0) { return HEAD_VIEW; }else{ return BODY_VIEW ; } }
The following operations will not be discussed much. We believe that this method is very skillful when using ListView. Since it can be implemented through the above method, why do we need to write a RecyclerView that can add HeaderView and FootView? In fact, you don't need to answer this question, because ListView can also be implemented through the above method, but it still has addHeaderView and addFootView methods, the addHeaderView can be used to add a header layout. For example, the ListView header image drop-down and zoom-in animation, and the adapter is called. notifyDataSetChanged () does not refresh the data in the header.
Well, the next step is the topic content of this article. How can we add HeaderView and FootView to RecyclerView?
Why? It doesn't matter! Does ListView help us implement this function? Let's first look at how ListView is implemented,
public void addHeaderView(View v, Object data, boolean isSelectable) { final FixedViewInfo info = new FixedViewInfo(); info.view = v; info.data = data; info.isSelectable = isSelectable; mHeaderViewInfos.add(info); mAreAllItemsSelectable &= isSelectable; // Wrap the adapter if it wasn't already wrapped. if (mAdapter != null) { if (!(mAdapter instanceof HeaderViewListAdapter)) { mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); } // In the case of re-adding a header view, or adding one later on, // we need to notify the observer. if (mDataSetObserver != null) { mDataSetObserver.onChanged(); } } }
The core code of the above method is
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
Others can be ignored. Here we actually use the concept of a design pattern. It seems like a decoration pattern. It means to repackage the original Adapter through the HeaderViewListAdapter package class, add an increment to the increment and a decrease to the increment. Therefore, we need to pay attention to how the HeaderViewListAdapter class is implemented, and then draw a RecyclerView package based on the gourd painting scheme. adapter packaging class!
Decrypt HeaderViewListAdapter
This Packaging code is not long enough. I believe everyone can understand it. here we will focus on it.
1. The count of the Adapter is recalculated. Do not explain it more!
public int getCount() { if (mAdapter != null) { return getFootersCount() + getHeadersCount() + mAdapter.getCount(); } else { return getFootersCount() + getHeadersCount(); } }
2. It is the getView method. This method is important. If the current position is smaller than the number of headerviews, the returned value is the View corresponding to HeaderView, otherwise, compare the difference between the count value of the original Adapter and the current position, whether to call the getView method of the original Adapter or get the view of the footView; the purpose of this method is to add the header and tail View.
public View getView(int position, View convertView, ViewGroup parent) { // Header (negative positions will throw an IndexOutOfBoundsException) int numHeaders = getHeadersCount(); if (position < numHeaders) { return mHeaderViewInfos.get(position).view; } // Adapter final int adjPosition = position - numHeaders; int adapterCount = 0; if (mAdapter != null) { adapterCount = mAdapter.getCount(); if (adjPosition < adapterCount) { return mAdapter.getView(adjPosition, convertView, parent); } } // Footer (off-limits positions will throw an IndexOutOfBoundsException) return mFooterViewInfos.get(adjPosition - adapterCount).view; }
For other methods of this packaging class, you only need to pay attention to it, so the next step is the moment we imitate it!
The code is very simple. Here we will go straight to it.
1. RecyclerWrapAdapter
Package moon. myapplication;
Import android. support. v7.widget. RecyclerView;
Import android. view. View;
Import android. view. ViewGroup;
Import java. util. ArrayList;
/**
* Created by moon. zhong on 2015/7/20.
* Time:
*/
Public class RecyclerWrapAdapter extends RecyclerView. Adapter implements WrapperAdapter {
private RecyclerView.Adapter mAdapter;private ArrayList<View> mHeaderViews;private ArrayList<View> mFootViews;static final ArrayList<View> EMPTY_INFO_LIST = new ArrayList<View>();private int mCurrentPosition;public RecyclerWrapAdapter(ArrayList<View> mHeaderViews, ArrayList<View> mFootViews, RecyclerView.Adapter mAdapter) { this.mAdapter = mAdapter; if (mHeaderViews == null) { this.mHeaderViews = EMPTY_INFO_LIST; } else { this.mHeaderViews = mHeaderViews; } if (mHeaderViews == null) { this.mFootViews = EMPTY_INFO_LIST; } else { this.mFootViews = mFootViews; }}public int getHeadersCount() { return mHeaderViews.size();}public int getFootersCount() { return mFootViews.size();}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == RecyclerView.INVALID_TYPE) { return new HeaderViewHolder(mHeaderViews.get(0)); } else if (viewType == RecyclerView.INVALID_TYPE - 1) { return new HeaderViewHolder(mFootViews.get(0)); } return mAdapter.onCreateViewHolder(parent, viewType);}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int numHeaders = getHeadersCount(); if (position < numHeaders) { return; } int adjPosition = position - numHeaders; int adapterCount = 0; if (mAdapter != null) { adapterCount = mAdapter.getItemCount(); if (adjPosition < adapterCount) { mAdapter.onBindViewHolder(holder, adjPosition); return; } }}@Overridepublic int getItemCount() { if (mAdapter != null) { return getHeadersCount() + getFootersCount() + mAdapter.getItemCount(); } else { return getHeadersCount() + getFootersCount(); }}@Overridepublic int getItemViewType(int position) { mCurrentPosition = position; int numHeaders = getHeadersCount(); if (position < numHeaders) { return RecyclerView.INVALID_TYPE; } int adjPosition = position - numHeaders; int adapterCount = 0; if (mAdapter != null) { adapterCount = mAdapter.getItemCount(); if (adjPosition < adapterCount) { return mAdapter.getItemViewType(adjPosition); } } return RecyclerView.INVALID_TYPE - 1;}@Overridepublic long getItemId(int position) { int numHeaders = getHeadersCount(); if (mAdapter != null && position >= numHeaders) { int adjPosition = position - numHeaders; int adapterCount = mAdapter.getItemCount(); if (adjPosition < adapterCount) { return mAdapter.getItemId(adjPosition); } } return -1;}@Overridepublic RecyclerView.Adapter getWrappedAdapter() { return mAdapter;}private static class HeaderViewHolder extends RecyclerView.ViewHolder { public HeaderViewHolder(View itemView) { super(itemView); }}
}
2. Add the AddHeaderView and addFootView methods for RecyclerView, and override RecyclerView.
package moon.myapplication;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.util.AttributeSet;import android.view.View;import java.util.ArrayList;/** * Created by moon.zhong on 2015/7/20. * time : 15:14 */public class WrapRecyclerView extends RecyclerView { private ArrayList<View> mHeaderViews = new ArrayList<>() ; private ArrayList<View> mFootViews = new ArrayList<>() ; private Adapter mAdapter ; public WrapRecyclerView(Context context) { super(context); } public WrapRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } public WrapRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void addHeaderView(View view){ mHeaderViews.clear(); mHeaderViews.add(view); if (mAdapter != null){ if (!(mAdapter instanceof RecyclerWrapAdapter)){ mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,mAdapter) ;// mAdapter.notifyDataSetChanged(); } } } public void addFootView(View view){ mFootViews.clear(); mFootViews.add(view); if (mAdapter != null){ if (!(mAdapter instanceof RecyclerWrapAdapter)){ mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,mAdapter) ;// mAdapter.notifyDataSetChanged(); } } } @Override public void setAdapter(Adapter adapter) { if (mHeaderViews.isEmpty()&&mFootViews.isEmpty()){ super.setAdapter(adapter); }else { adapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,adapter) ; super.setAdapter(adapter); } mAdapter = adapter ; }}
Now we have implemented the RecyclerView to add headers and tail la S, which are easy to use and remain unchanged in other steps. You only need to replace RecyclerView with WrapRecyclerView.
Look
This article does not have any innovative technical points, but it gives programmers a good idea: imitation. It is best to do it yourself. Maybe you can understand it once you read it, however, you may find many problems in practice!
Source code Download
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.