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

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

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

public class XRecyclerView extends RecyclerView {

    //用来存储添加的headerView和footerView
    private ArrayList mHeadView = new ArrayList<>();
    private ArrayList 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 mHeadView;
    private ArrayList mFootView;
    private RecyclerView.Adapter mAdapter;

    public HeaderViewRecyclerAdapter(ArrayList HeadView, ArrayList 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 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 {


        private List list;

        public MyAdapter(List 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,这个对象池不能复用,因为头和脚可以是各种不同类型的***,一旦添加多个头和脚的时候就有问题,这个问题待搞定。

你可能感兴趣的:(Android)