RecyclerView添加头部(addHeaderView)和脚部(addFooterView)的封装

来源:互联网 发布:android 彩票app源码 编辑:程序博客网 时间:2024/06/08 07:40

RecyclerView的功能强大之处就不用说了,但是相比于listview来说,它也有些小缺点,比如:没有了间隔线divider,没有addHeaderViewaddFooterView等方法,所以用起来不是那么方便。今天主要完成RecyclerView的addHeaderView和addFooterView方法。
运行效果如下:

这里写图片描述

第一步:自定义RecyclerView,代码如下:

public class XRecyclerView extends RecyclerView {    //用来存储添加的headerView和footerView    private ArrayList<View> mHeadView = new ArrayList<>();    private ArrayList<View> mFootView = new ArrayList<>();    //RecyclierView的适配器    private Adapter mAdapter;    public XRecyclerView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    //添加头部view,仿ListView的源码改造    public void addHeaderView(View headerView) {        mHeadView.add(headerView);        if (mAdapter != null) {            if (!(mAdapter instanceof HeaderViewRecyclerAdapter)) {                mAdapter = new HeaderViewRecyclerAdapter(mHeadView,mFootView, mAdapter);            }        }    }    //添加脚View    public void addFooterView(View footView) {        mFootView.add(footView);        if (mAdapter != null) {            if (!(mAdapter instanceof HeaderViewRecyclerAdapter)) {                mAdapter = new HeaderViewRecyclerAdapter(mHeadView,mFootView, mAdapter);            }        }    }    @Override    public void setAdapter(Adapter adapter) {        //参考listview方法 setAdapter的源码,对adapter进行更换        if (mHeadView.size() > 0 || mFootView.size() > 0)            mAdapter = new HeaderViewRecyclerAdapter(mHeadView, mFootView, adapter);        else {            mAdapter = adapter;        }        super.setAdapter(mAdapter);    }}

第二步自定义RecyclerView的adapter,代码如下:

public class HeaderViewRecyclerAdapter extends RecyclerView.Adapter {    private final int HEADER = 1;    private final int FOOTER = 2;    private ArrayList<View> mHeadView;    private ArrayList<View> mFootView;    private RecyclerView.Adapter mAdapter;    public HeaderViewRecyclerAdapter(ArrayList<View> HeadView, ArrayList<View> FootView, RecyclerView.Adapter adapter) {        mAdapter = adapter;        if (HeadView == null) {            //为了防止空指针异常            mHeadView = new ArrayList<>();        } else {            mHeadView = HeadView;        }        if (FootView == null) {            mFootView = new ArrayList<>();        } else {            mFootView = FootView;        }    }    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        //头部修改newHeadViewHolder的方法,mFooterView,有几个头,就需要几个headViewHolder        if (viewType == HEADER) {            return new HeadViewHolder(mHeadView.get(0));        } else if (viewType == FOOTER) {            //脚部,修改newHeadViewHolder的方法,mFooterView,有多个            return new FootViewHolder(mFootView.get(0));        }        //body部分,暴露出去操作        return mAdapter.onCreateViewHolder(parent, viewType);    }    //判断view的类型,头,身体,脚    @Override    public int getItemViewType(int position) {        int headcount = getHeadCount();        //返回头部        if (position < headcount) {            //返回头部类型,            return HEADER;        }        //body类型        final int midPosition = position - headcount;        int itemCount = 0;        if (mAdapter != null) {            itemCount = mAdapter.getItemCount();            if (midPosition < itemCount) {                //返回type不要写死了,body的类型可能不一致                return mAdapter.getItemViewType(midPosition);            }        }        //Footer类型        return FOOTER;    }    /**     * 和数据绑定,这里只做body部分的绑定     * 头和脚的数据绑定逻辑都是在外部操作的     * 传入前都已经绑定好l     */    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        int headcount = getHeadCount();        if (position < headcount) {            //头部数据绑定,外部传入前已经操作,这里不再操作            return;        }        //body数据绑定        final int midPosition = position - headcount;        int itemcount = 0;        if (mAdapter != null) {            itemcount = mAdapter.getItemCount();            if (midPosition < itemcount) {                //暴露出去自由操作,传入的是调整后的位置,而不是算上头角的位置//                mAdapter.onBindViewHolder(holder, position);                mAdapter.onBindViewHolder(holder, midPosition);                return;            }        }        //脚部数据绑定,和头一样,啥也不用操作    }    @Override    public int getItemCount() {        //身体部分不为空        if (mAdapter != null) {            return getHeadCount() + getFootCount() + mAdapter.getItemCount();        } else {            //只有头和脚的情况下            return getHeadCount() + getFootCount();        }    }    private int getFootCount() {        return mFootView.size();    }    public int getHeadCount() {        return mHeadView.size();    }    /**     * 面两个head viewholder 没什么卵用     * viewholder是为了相同的item减少findviewbyid的时间     * 头部holder和尾部holder没有共性的findviewbyid     * 为了拓展方便只得创建,但是不会用到     */    class HeadViewHolder extends RecyclerView.ViewHolder {        public HeadViewHolder(View itemView) {            super(itemView);        }    }    class FootViewHolder extends RecyclerView.ViewHolder {        public FootViewHolder(View itemView) {            super(itemView);        }    }}

第三步,就是在activity中使用刚才写的recyclerview,代码如下:

public class MainActivity extends AppCompatActivity {    private XRecyclerView recyclerView;    private List<String> list = new ArrayList<>();    private View headView;    private View footView;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        recyclerView = ((XRecyclerView) findViewById(R.id.recyclerView));        initData();        initHeaderView();        recyclerView.addHeaderView(headView);        recyclerView.addFooterView(footView);        MyAdapter adapter = new MyAdapter(list);        recyclerView.setLayoutManager(new LinearLayoutManager(this));        recyclerView.setAdapter(adapter);    }    private void initHeaderView() {        headView = LayoutInflater.from(this).inflate(R.layout.header, null);        footView = LayoutInflater.from(this).inflate(R.layout.footer, null);    }    private void initData() {        for (int i = 0; i < 10; i++) {            list.add("我是身体body" + i);        }    }    class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {        private List<String> list;        public MyAdapter(List<String> list) {            this.list = list;        }        @Override        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {            View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item, parent, false);            MyViewHolder holder = new MyViewHolder(itemView);            return holder;        }        @Override        public void onBindViewHolder(MyViewHolder holder, int position) {            holder.text.setText(list.get(position));        }        @Override        public int getItemCount() {            return list.size();        }        class MyViewHolder extends RecyclerView.ViewHolder {            TextView text;            public MyViewHolder(View itemView) {                super(itemView);                text = (TextView) itemView.findViewById(R.id.tv_item);            }        }    }}

总结:这种方法只能添加一个头和一个脚,本来是想能任意添加头和脚的,后来发现有点问题,

   if (viewType == HEADER) {            return new HeadViewHolder(mHeadView.get(0));        } else if (viewType == FOOTER) {            //脚部,修改newHeadViewHolder的方法,mFooterView,有多个            return new FootViewHolder(mFootView.get(0));        }        //body部分,暴露出去操作        return mAdapter.onCreateViewHolder(parent, viewType);

在viewholder创建的时候,头部和尾部也有viewholder,这个对象池不能复用,因为头和脚可以是各种不同类型的***,一旦添加多个头和脚的时候就有问题,这个问题待搞定。

2 0