RecyclerView添加addHeader和addFooter方法

来源:互联网 发布:淘宝哪家女童卖的好 编辑:程序博客网 时间:2024/06/05 07:00

在新版本的android系统中RecyclerView作为ListView的优化版本,封装了ViewHolder,这样就可以更加方便的使用这个控件。但是相比较ListView,RecyclerView没有提供相应的addHeaderView和addFooterView方法,我们知道在一些下拉控件的实现中,都是设置了headerView或者是footerView,然后不断的设置padding来实现的。那既然RecyclerView没有addHeaderView和addFooterView这些方法,那么是不是就不能实现下拉刷新这样的功能了呢?当然不是。下面就带大家实现一个简易的实现addHeaderView和addFooterView的方法。

我们知道像需要适配器的这些控件,它们的数据都是通过Adapter的提供的。那么我们就着手改造我们的Adapter。首先我们创建一个自定义的Adapter类继承RecyclerView.Adapter

    public class HeaderRecyclerViewAdapter extends RecyclerView.Adapter<HeaderRecyclerViewAdapter            .HeaderViewHolder> {       //header view type的开始值       private final int RECYCLER_HEADER_TYPE_BASE = 0xff11;       //footer view type的开始值       private final int RECYCLER_FOOTER_TYPE_BASE = 0xff22;       //header和footer的id值       private final int RECYCLER_HEADER_FOOTER_ID = -1;       //用来存放所有的header view的信息       private List<FixedInfo> mHeaders = new ArrayList<>();       //用来存放所有的footer view的信息       private List<FixedInfo> mFooters = new ArrayList<>();       //保存使用默认的RecyclerView.Adapter创建的adapter的值,这个值必须获取到       private RecyclerView.Adapter mAdapter = null;       public HeaderRecyclerViewAdapter() {       }       public HeaderRecyclerViewAdapter(RecyclerView.Adapter adapter) {          this.mAdapter = adapter;       }       public void setAdapter(RecyclerView.Adapter adapter) {          this.mAdapter = adapter;       }

我们创建一个HeaderRecyclerViewAdapter类用来包装我们原始的RecyclerView.Adapter类,mAdpter就是对这个原始类的应用。同样创建了两个ArrayList用来保存我们的Headers和footers,这里面有一个FixedInfo类,这个类是干嘛的呢?

    //用来保存footer和headers的信息    private class FixedInfo {      public View view;      public int type;    }

这个类比较简单,view保存我们设置的view,type用来保存我们view的type信息,可以通过type信息识别我们的header和footer。

  public void addHeader(View view) {      FixedInfo info = new FixedInfo();      info.view = view;      info.type = RECYCLER_HEADER_TYPE_BASE + mHeaders.size();      mHeaders.add(info);    }    public void addFooter(View view) {      FixedInfo info = new FixedInfo();      info.view = view;      info.type = RECYCLER_FOOTER_TYPE_BASE + mFooters.size();      mFooters.add(info);    }

可以看到,每次addHeader或者是addFooter的时候,都通过一个唯一的type信息来区别这个view。

@Override    public long getItemId(int position) {      int headerCount = getHeaderSize();      if (mAdapter != null && position >= headerCount) {         int adjPosition = position - headerCount;         return mAdapter.getItemId(adjPosition);      }      return RECYCLER_HEADER_FOOTER_ID;    }

我们需要重新getItemId()方法,如果是header或者是footer的话,直接返回我们定义的特殊值 RECYCLER_HEADER_FOOTER_ID。如果是adapter中的数据则返回adapter中的相同方法。

 @Override    public int getItemViewType(int position) {      if (mAdapter == null) {         throw new IllegalStateException("must have a adapter");      }      int headerCount = getHeaderSize();      int adapterCount = mAdapter.getItemCount();      if (position < headerCount) {         return mHeaders.get(position).type;      } else if (position >= (headerCount + adapterCount)) {         return mFooters.get(position - headerCount - adapterCount).type;      } else {         int adjPosition = position - headerCount;         return mAdapter.getItemViewType(adjPosition);      }    }  

getItemViewType()是我们必须重写的方法,在这个方法中,我们会标识每一个Header和Footer的viewType。

 @Override    public HeaderViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {      if (isHeaderView(viewType)) {         int delta = viewType - RECYCLER_HEADER_TYPE_BASE;         View view = mHeaders.get(delta).view;         return new HeaderViewHolder(view);      }      if (isFooterView(viewType)) {         int delta = viewType - RECYCLER_FOOTER_TYPE_BASE;         View view = mFooters.get(delta).view;         return new HeaderViewHolder(view);      }      return (HeaderViewHolder) mAdapter.onCreateViewHolder(parent,viewType);    }    @Override    public void onBindViewHolder(HeaderViewHolder holder, int position) {      int headerCount = getHeaderSize();      if (mAdapter != null && position >= headerCount) {         int adapterCount = mAdapter.getItemCount();         int adjPosition = position - headerCount;         if (adjPosition >= 0 && adjPosition < adapterCount) {            mAdapter.onBindViewHolder(holder, adjPosition);         }      }    }

最主要的地方来了,在onCreateViewHolder中,我们需要判断当前的viewType是header的还是footer的,如果是header的或者footer的,我们需要算出这个viewtype所对应的view,用这个view来返回HeaderViewHolder。而在onBindViewHolder()方法中,我们只需要定位到属于adapter中的数据就好,然后返回对应的方法即可。完整的代码如下:

 package com.gearmotion.app.mylibrary;    import android.support.v7.widget.RecyclerView;    import android.view.View;    import android.view.ViewGroup;    import java.util.ArrayList;    import java.util.List;    /**     * Created by Charles on 2016/3/21.     */    public class HeaderRecyclerViewAdapter extends RecyclerView.Adapter<HeaderRecyclerViewAdapter        .HeaderViewHolder> {       //header view type的开始值       private final int RECYCLER_HEADER_TYPE_BASE = 0xff11;       //footer view type的开始值       private final int RECYCLER_FOOTER_TYPE_BASE = 0xff22;       //header和footer的id值       private final int RECYCLER_HEADER_FOOTER_ID = -1;       //用来存放所有的header view的信息       private List<FixedInfo> mHeaders = new ArrayList<>();       //用来存放所有的footer view的信息       private List<FixedInfo> mFooters = new ArrayList<>();       //保存使用默认的RecyclerView.Adapter创建的adapter的值,这个值必须获取到       private RecyclerView.Adapter mAdapter = null;       public HeaderRecyclerViewAdapter() {       }       public HeaderRecyclerViewAdapter(RecyclerView.Adapter adapter) {          this.mAdapter = adapter;       }       public void setAdapter(RecyclerView.Adapter adapter) {          this.mAdapter = adapter;       }       @Override       public HeaderViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {      if (isHeaderView(viewType)) {         int delta = viewType - RECYCLER_HEADER_TYPE_BASE;         View view = mHeaders.get(delta).view;         return new HeaderViewHolder(view);      }      if (isFooterView(viewType)) {         int delta = viewType - RECYCLER_FOOTER_TYPE_BASE;         View view = mFooters.get(delta).view;         return new HeaderViewHolder(view);      }      return (HeaderViewHolder) mAdapter.onCreateViewHolder(parent,viewType);     }       @Override       public void onBindViewHolder(HeaderViewHolder holder, int position) {      int headerCount = getHeaderSize();      if (mAdapter != null && position >= headerCount) {         int adapterCount = mAdapter.getItemCount();         int adjPosition = position - headerCount;         if (adjPosition >= 0 && adjPosition < adapterCount) {            mAdapter.onBindViewHolder(holder, adjPosition);         }      }    }    @Override    public int getItemCount() {      if (mAdapter != null) {         return mHeaders.size() + mAdapter.getItemCount() + mFooters.size();      } else {         return mHeaders.size() + mFooters.size();      }    }    @Override    public int getItemViewType(int position) {      if (mAdapter == null) {         throw new IllegalStateException("must have a adapter");      }      int headerCount = getHeaderSize();      int adapterCount = mAdapter.getItemCount();      if (position < headerCount) {         return mHeaders.get(position).type;      } else if (position >= (headerCount + adapterCount)) {         return mFooters.get(position - headerCount - adapterCount).type;      } else {         int adjPosition = position - headerCount;         return mAdapter.getItemViewType(adjPosition);      }   }    @Override    public long getItemId(int position) {      int headerCount = getHeaderSize();      if (mAdapter != null && position >= headerCount) {         int adjPosition = position - headerCount;         return mAdapter.getItemId(adjPosition);      }      return RECYCLER_HEADER_FOOTER_ID;    }    public void addHeader(View view) {      FixedInfo info = new FixedInfo();      info.view = view;      info.type = RECYCLER_HEADER_TYPE_BASE + mHeaders.size();      mHeaders.add(info);    }    public void addFooter(View view) {      FixedInfo info = new FixedInfo();      info.view = view;      info.type = RECYCLER_FOOTER_TYPE_BASE + mFooters.size();      mFooters.add(info);    }    public int getHeaderSize() {      return mHeaders.size();    }    public int getFooterSize() {      return mFooters.size();    }    private boolean isHeaderView(int type) {      int delta = type - RECYCLER_HEADER_TYPE_BASE;      return delta >= 0 && delta < mHeaders.size();    }    private boolean isFooterView(int type) {      int delta = type - RECYCLER_FOOTER_TYPE_BASE;      return delta >= 0 && delta < mFooters.size();    }    //用来保存footer和headers的信息    private class FixedInfo {      public View view;      public int type;    }    //自定义的viewholder    public static class HeaderViewHolder extends RecyclerView.ViewHolder {      public HeaderViewHolder(android.view.View itemView) {         super(itemView);      }    }    }

最后我们在使用的时候将原始创建的adapter传递给HeaderRecyclerViewAdapter即可。

package com.gearmotion.app.headerrecyclerviewmotion;     import android.support.v7.app.AppCompatActivity;     import android.os.Bundle;     import android.support.v7.widget.LinearLayoutManager;     import android.support.v7.widget.RecyclerView;     import android.text.Layout;     import android.view.Gravity;     import android.view.LayoutInflater;     import android.view.View;     import android.view.ViewGroup;     import android.widget.TextView;    import com.gearmotion.app.mylibrary.HeaderRecyclerViewAdapter;    public class MainActivity extends AppCompatActivity {    private RecyclerView mRecyclerView;    private LayoutInflater mInflater;    private String[] mDatas = new String[]{"title1", "title2", "title3", "title4", "title5",           "title6"};    @Override    protected void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      setContentView(R.layout.activity_main);      mInflater = LayoutInflater.from(this);      mRecyclerView = (RecyclerView) this.findViewById(R.id.recyclerview);      mRecyclerView.setLayoutManager(new LinearLayoutManager(this));      CustomAdapter tmpAdapter = new CustomAdapter();      HeaderRecyclerViewAdapter mAdapter = new HeaderRecyclerViewAdapter(tmpAdapter);      mAdapter.addHeader(createView("head1"));      mAdapter.addHeader(createView("head2"));      mAdapter.addHeader(createView("head3"));      mAdapter.addFooter(createView("foot1"));      mAdapter.addFooter(createView("foot2"));      mAdapter.addFooter(createView("foot3"));      mRecyclerView.setAdapter(mAdapter);    }    private View createView(String title) {      TextView tv = new TextView(this);      tv.setText(title);      tv.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,              70));      tv.setGravity(Gravity.CENTER);      return tv;    }    public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {      @Override      public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {         View root = mInflater.inflate(R.layout.item, null);         return new CustomViewHolder(root);      }      @Override      public void onBindViewHolder(CustomViewHolder holder, int position) {         holder.textView.setText(mDatas[position]);      }      @Override      public int getItemCount() {         return mDatas.length;      }    }    public class CustomViewHolder extends HeaderRecyclerViewAdapter.HeaderViewHolder {      public TextView textView;      public CustomViewHolder(View itemView) {         super(itemView);         textView = (TextView) itemView.findViewById(R.id.itemtextview);      }    }    }

结果如下:

代码地址如下:https://github.com/summerpxy/HeaderRecyclerViewAdapter.git

0 0
原创粉丝点击