Android RecyclerView Method for Adding Header and Bottom

  • 2021-07-13 06:09:00
  • OfStack

If you just want to add headers, you can use this project in GitHub to add header to RecyclerView with LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager layouts. It is also 10 points simple to use;
Simply put the RecyclerViewHeader layout on top of the RecyclerView.


<FrameLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content">

 <android.support.v7.widget.RecyclerView
  android:id="@+id/recycler"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_gravity="center_horizontal|top" />

 <com.bartoszlipinski.recyclerviewheader.RecyclerViewHeader
  android:id="@+id/header"
  android:layout_width="match_parent"
  android:layout_height="100dp"
  android:layout_gravity="center_horizontal|top">

  <TextView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerInParent="true"
   android:text="header"/>

 </com.bartoszlipinski.recyclerviewheader.RecyclerViewHeader>

</FrameLayout>

Then get the RecyclerViewHeader object:

RecyclerViewHeader header = (RecyclerViewHeader) findViewById(R.id.header);

Give RecyclerViewHeader to RecyclerView


RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// set LayoutManager for your RecyclerView
header.attachTo(recyclerView, true);

Matters needing attention
RecyclerViewHeader must be called after RecyclerView has set LayoutManager.

The library is currently available for RecyclerViews with LinearLayoutManager, StaggeredGridLayoutManager, and GridLayoutManager layouts. Only vertical layout LayoutManager is supported. If you plan to use the setOnScrollListener (...) method in RecyclerView, be sure to use it before the attachTo (...) method in setOnScrollListener (...).

Of course, we can also write an RecyclerView with a head and a bottom. The basic principle of its implementation is also to add headers and bottoms by returning different types through the getItemViewType method.
First, we customize an RecyclerView:


public class WrapRecyclerView extends RecyclerView {
 public ArrayList<View> mHeaderViews = new ArrayList<>();
 public ArrayList<View> mFooterViews = new ArrayList<>();
 // Add Adapter
 public Adapter mAdapter;
 public WrapRecyclerView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
 }

 public WrapRecyclerView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }

 public WrapRecyclerView(Context context) {
  super(context);
 }
 public void addHeaderView(View view){
  mHeaderViews.clear();
  mHeaderViews.add(view);
  if(mAdapter!=null){
   if(!(mAdapter instanceof RecyclerWrapAdapter)){
    mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,mAdapter);
   }
  }
 }
 public void addFooterView(View view){
  mFooterViews.clear();
  mFooterViews.add(view);
  if(mAdapter!=null){
   if(!(mAdapter instanceof RecyclerWrapAdapter)){
    mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,mAdapter);
   }
  }
 }
 public void setAdapter(Adapter adapter){
  if (mHeaderViews.isEmpty()&&mFooterViews.isEmpty()){

   super.setAdapter(adapter);
  }else {
   adapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,adapter) ;
   super.setAdapter(adapter);
  }
  mAdapter = adapter ;
 }
}

We will see that we have one RecyclerWrapAdapter that is not implemented, so let's look at RecyclerWrapAdapter, which is also the key to adding headers and tails.


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 (mFootViews == null) {
   this.mFootViews = EMPTY_INFO_LIST;
  } else {
   this.mFootViews = mFootViews;
  }
 }

 public int getHeadersCount() {
  return mHeaderViews.size();
 }

 public int getFootersCount() {
  return mFootViews.size();
 }
 @Override
 public 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);
 }

 @Override
 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
  // If the head is not empty, then we have to add the head first, so we just need to 
  // Put the first few position To the head, when position When it is less than the total number of heads, 
  // Let's go back to the head view . Re-judge the original Adapter  Adj.  count  And the current  position 
  //  To compare, is to call the original  Adapter  Adj.  getView  Method, or get the  footView
  //  Adj.  view . 
  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;
   }
  }
 }

 @Override
 public int getItemCount() {
  if (mAdapter != null) {
   return getHeadersCount() + getFootersCount() + mAdapter.getItemCount();
  } else {
   return getHeadersCount() + getFootersCount();
  }
 }

 @Override
 public RecyclerView.Adapter getWrappedAdapter() {
  return mAdapter;
 }
 @Override
 public int getItemViewType(int position) {
  // Add two types 
  //RecyclerView.INVALID_TYPE  Add headers 
  //RecyclerView.INVALID_TYPE-1  Add tail 
  // If the head is not empty, then we have to add the head first, so we just need to 
  // Put the first few position To the head, when position When it is less than the total number of heads, 
  // We return to the head type. Re-judge the original Adapter  Adj.  count  And the current  position 
  //  To compare, is to call the original  Adapter  Adj.   Type, or get the  footView
  //  The type of. 
  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;
 }
 private static class HeaderViewHolder extends RecyclerView.ViewHolder {
  public HeaderViewHolder(View itemView) {
   super(itemView);
  }
 }
}

We can also implement an interface to call the RecyclerWrapAdapter object:


public interface WrapperAdapter {

 public RecyclerView.Adapter getWrappedAdapter() ;
}

So we can change the layout of RecyclerView to WrapRecyclerView, and then call addHeaderView or addFooterView to add headers and trails.

The above is the whole content of this article, hoping to help you learn Android software programming.


Related articles: