• RecyclerView添加addHeader和addFooter方法


    在新版本的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

  • 相关阅读:
    Class:向传统类模式转变的构造函数
    连载:面向对象葵花宝典:思想、技巧与实践(34)
    Java Web文件下载
    POJ 1469(裸二分匹配)
    查看程序占用tomcat内存情况
    《对象程序设计》课程 课程设计、考试安排 及 教师建议(2014.06.30修正)
    zoj 1880
    STM8S PWM 应用 呼吸灯
    Android开发系列(二十四):Notification的功能与使用方法
    HDU 4499 Cannon (暴力搜索)
  • 原文地址:https://www.cnblogs.com/summerpxy/p/13648337.html
Copyright © 2020-2023  润新知