• RecyclerView添加头部和底部视图的实现


    ListView是有addHeaderView和 addFooterView两个方法的.

    但是作为官方推荐的ListView的升级版RecyclerView缺无法实现这两个方法。

    那么如果使用RecyclerView实现这两个方法的效果该怎么做呢?

    网上查询了很久,试过各种各样的实现方式,终于让我发现一个还不错的实现方法,那么就给大家推荐一下。

    项目地址(别人写的,非博主的)https://github.com/jczmdeveloper/XCRecyclerView

    我看了下这个源码,很简单,即写了一个继承RecyclerView的控件,自己实现addHeaderView和addFooterView两个方法

    package com.xqx.com.recyclerviewheaderdemo;
    
    import android.content.Context;
    import android.support.v7.widget.RecyclerView;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewGroup;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class XCRecyclerView extends RecyclerView{
    
        private ArrayList<View> mHeaderViews = new ArrayList<>();
        private ArrayList<View> mFooterViews = new ArrayList<>();
        private RecyclerView.Adapter mAdapter;
        private RecyclerView.Adapter mWrapAdapter;
        private static final int TYPE_HEADER = -101;
        private static final int TYPE_FOOTER  = -102;
        private static final int TYPE_LIST_ITEM = - 103;
        public XCRecyclerView(Context context) {
            this(context, null);
        }
        public XCRecyclerView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
        public XCRecyclerView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init(context);
        }
        private void init(Context context){
    
        }
    
        @Override
        public void setAdapter(Adapter adapter) {
            mAdapter = adapter;
            mWrapAdapter = new WrapAdapter(mHeaderViews, mFooterViews, adapter);
            super.setAdapter(mWrapAdapter);
            mAdapter.registerAdapterDataObserver(mDataObserver);
        }
        public void addHeaderView(View view){
            mHeaderViews.clear();
            mHeaderViews.add(view);
        }
        public void addFooterView(View view){
            mFooterViews.clear();
            mFooterViews.add(view);
        }
        public int getHeaderViewsCount(){
            return mHeaderViews.size();
        }
        public int getFooterViewsCount(){
            return mFooterViews.size();
        }
        private final RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {
            @Override
            public void onChanged() {
                mWrapAdapter.notifyDataSetChanged();
            }
    
            @Override
            public void onItemRangeChanged(int positionStart, int itemCount) {
                mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount);
            }
    
    //        @Override
    //        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
    //            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload);
    //        }
    
            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                mWrapAdapter.notifyItemRangeInserted(positionStart, itemCount);
            }
    
            @Override
            public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
                mWrapAdapter.notifyItemMoved(fromPosition, toPosition);
            }
    
            @Override
            public void onItemRangeRemoved(int positionStart, int itemCount) {
                mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount);
            }
        };
        private class WrapAdapter extends RecyclerView.Adapter<ViewHolder>{
    
            private Adapter mAdapter;
            private List<View> mHeaderViews;
            private List<View> mFooterViews;
            public WrapAdapter(List<View> headerViews,List<View> footerViews,Adapter adapter){
                this.mAdapter = adapter;
                this.mHeaderViews = headerViews;
                this.mFooterViews = footerViews;
            }
    
            public int getHeaderCount(){
                return this.mHeaderViews.size();
            }
            public int getFooterCount(){
                return this.mFooterViews.size();
            }
            public boolean isHeader(int position){
                return position >= 0 && position < this.mHeaderViews.size();
            }
            public boolean isFooter(int position){
                return position < getItemCount() && position >= getItemCount() - this.mFooterViews.size();
            }
            @Override
            public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                if(viewType == TYPE_HEADER){
                    return new CustomViewHolder(this.mHeaderViews.get(0));
                }else if(viewType == TYPE_FOOTER){
                    return new CustomViewHolder(this.mFooterViews.get(0));
                }else{
                    return this.mAdapter.onCreateViewHolder(parent,viewType);
                }
            }
    
            @Override
            public void onBindViewHolder(ViewHolder holder, int position) {
                if(isHeader(position)) return;
                if(isFooter(position)) return;
                int rePosition = position - getHeaderCount();
                int itemCount = this.mAdapter.getItemCount();
                if(this.mAdapter != null){
                    if(rePosition < itemCount){
                        Log.v("czm","rePosition/itemCount="+rePosition+"/"+itemCount);
                        this.mAdapter.onBindViewHolder(holder,rePosition);
                        return;
                    }
                }
            }
            @Override
            public long getItemId(int position) {
                if (this.mAdapter != null && position >= getHeaderCount()) {
                    int rePosition = position - getHeaderCount();
                    int itemCount = this.mAdapter.getItemCount();
                    if (rePosition < itemCount) {
                        return this.mAdapter.getItemId(rePosition);
                    }
                }
                return -1;
            }
            @Override
            public int getItemViewType(int position) {
                if(isHeader(position)){
                    return TYPE_HEADER;
                }
                if(isFooter(position)){
                    return TYPE_FOOTER;
                }
                int rePosition = position - getHeaderCount();
                int itemCount = this.mAdapter.getItemCount();
                if(rePosition < itemCount){
                    return this.mAdapter.getItemViewType(position);
                }
                return TYPE_LIST_ITEM;
            }
            @Override
            public int getItemCount() {
                if(this.mAdapter != null){
                    return getHeaderCount() + getFooterCount() + this.mAdapter.getItemCount();
                }else{
                    return getHeaderCount() + getFooterCount();
                }
            }
    
            @Override
            public void registerAdapterDataObserver(AdapterDataObserver observer) {
                if(this.mAdapter != null){
                    this.mAdapter.registerAdapterDataObserver(observer);
                }
            }
    
            @Override
            public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
                if(this.mAdapter != null){
                    this.mAdapter.unregisterAdapterDataObserver(observer);
                }
            }
    
            private class CustomViewHolder extends ViewHolder{
    
                public CustomViewHolder(View itemView) {
                    super(itemView);
                }
            }
        }
    }
    XCRecyclerView

    使用方法github里也写的清清楚楚的

    private MyAdapter mAdapter;
    private XCRecyclerView mRecyclerView;
    private List<String> mData;
    private View mHeaderView;
    private View mFooterView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mData = new  ArrayList<String>();
        for(int i = 0; i < 10 ;i++){
            mData.add("item_" + i);
        }
        mAdapter = new MyAdapter(mData);
        mRecyclerView = (XCRecyclerView) findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mHeaderView = LayoutInflater.from(this).inflate(R.layout.layout_header,mRecyclerView,false);
        mFooterView = LayoutInflater.from(this).inflate(R.layout.layout_footer,mRecyclerView,false);
        mRecyclerView.addHeaderView(mHeaderView);
        mRecyclerView.addFooterView(mFooterView);
        mRecyclerView.setAdapter(mAdapter);
    }

    注意点:

    addHeaderView之后 列表的数据坐标即相应发生变化!即addHeadView一次,列表第一个数据的下坐标+1(0-->1)

    adapter.notifyItemChanged();等方法的坐标类似,都要相应的变化。

    比如你addHeadView()一次

    那么你想更新列表第4个列表项的视图,则adapter.notifyItemChanged(3+1);  多加1  headView也算一个列表项。 

  • 相关阅读:
    Linux安装配置tomcat
    linux 安装jdk
    让/etc/profile文件修改后立即生效
    group by 和聚合函数
    mysql插入日期 vs oracle插入日期
    Thinkphp学习笔记-删除缓存
    Thinkphp错误-phpMyAdmin 尝试连接到 MySQL 服务器,但服务器拒绝连
    Thinkphp学习笔记-模板赋值
    Thinkphp学习笔记-模板主题
    Windows-设置系统服务不开机启动
  • 原文地址:https://www.cnblogs.com/xqxacm/p/5190740.html
Copyright © 2020-2023  润新知