`

如何给RecyclerView(GridLayoutManager)添加多个Header和Footer

阅读更多

基于前面的博文给RecyclerView添加Header,给RecyclerView添加多个Header

通过上节的内容,我们知道了给RecyclerView(GridLayoutManager)添加Header的方法

 
1.首先初始化了一个HeaderView用于下拉刷新使用并且将这个下拉刷新的布局添加到头布局

 

 

/**
     * 初始化头布局
     */
    private void initHeaderView() {
        header = RecyclerViewHeader.fromXml(getContext(), R.layout.refresh_header);

        // 添加HeaderView
        this.addHeaderView(header);

        tvTitle = (TextView) header.findViewById(R.id.tv_title);
        tvTime = (TextView) header.findViewById(R.id.tv_time);
        ivArrow = (ImageView) header.findViewById(R.id.iv_arr);
        pbProgress = (ProgressBar) header.findViewById(R.id.pb_progress);

        header.measure(0, 0);
        headerHeight = header.getMeasuredHeight();

        // 隐藏头布局
        header.setPadding(0, -headerHeight, 0, 0);    //  负的值就能够让控件向上移动了
        initArrowAnim();        // 初始化箭头动画
        // 更新最后刷新的时间
        tvTime.setText("最后刷新时间" + getCurrentTime());
    }

 

 

 

2.在添加头布局的时候,首先先是将原先拥有的HeaderView全部都清除了,接着再将需要添加的View添加进去,值得注意的是,就是这个clear操作导致了我们自己自定义的addHeaderView方法只能够添加一个HeaderView

 

 /**
     * 添加头布局
     *
     * @param view
     */
    public void addHeaderView(View view) {
        mHeaderViews.clear();
        mHeaderViews.add(view);
        if (mAdapter != null) {
            if (!(mAdapter instanceof RecyclerWrapAdapter)) {
                mAdapter = new RecyclerWrapAdapter(mHeaderViews, mFooterViews, mAdapter);
                mAdapter.notifyDataSetChanged();
            }
        }
    }

 

3.在addHeaderView中实例化RecyclerWrapAdapter,这个RecyclerWrapAdapter就是整个自定义RecyclerView中最核心的部分,我们挑选最重要的地方来看

 

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == RecyclerView.INVALID_TYPE) {
            return new HeaderViewHolder(mHeaderViews.get(0));   // 将第一个HeaderView封装
        } else if (viewType == RecyclerView.INVALID_TYPE - 2) {
            return new HeaderViewHolder(mFooterViews.get(0));   // 将FooterView封装
        }
        return mAdapter.onCreateViewHolder(parent, viewType);
    }

 

@Override
    public int getItemViewType(int position) {
        if (mCurrentPosition == -1) {
            mCurrentPosition = position;    // 这是第一个HeaderView
        }
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {
            return RecyclerView.INVALID_TYPE;   // 这是第一个HeaderView所占用的空间
        }
        int adjPosition = position - numHeaders;
        int adapterCount = 0;
        if (mAdapter != null) {
            adapterCount = mAdapter.getItemCount();
            if (adjPosition < adapterCount) {
                return mAdapter.getItemViewType(adjPosition);
            }
        }
        return RecyclerView.INVALID_TYPE - 2;   // 说明是Footer的所占用的空间
    }

 这两段代码就是最重要的地方,我们会发现,getViewType返回的值被引用成了onCreateViewHolder的参数所以我们如果想要添加多个HeaderView就需要在这里入手。

 

 

添加多个HeaderView的具体方法:

1.我们将RecyclerWrapAdapter中的核心方法修改下,修改成可以添加两个HeaderView的

 

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == RecyclerView.INVALID_TYPE) {
            return new HeaderViewHolder(mHeaderViews.get(0));   // 将第一个HeaderView封装
        } else if(viewType == RecyclerView.INVALID_TYPE - 1){
            return new HeaderViewHolder(mHeaderViews.get(1));   // 将第二个HeaderView封装
        } else if (viewType == RecyclerView.INVALID_TYPE - 2) {
            return new HeaderViewHolder(mFooterViews.get(0));   // 将FooterView封装
        }
        return mAdapter.onCreateViewHolder(parent, viewType);
    }

 

@Override
    public int getItemViewType(int position) {
        if (mCurrentPosition == -1) {
            mCurrentPosition = position;    // 这是第一个HeaderView
        }
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {
            if (position != mCurrentPosition) {  // 这是第二个HeaderView
                return RecyclerView.INVALID_TYPE - 1;   // 这是第二个HeaderView所占用的空间
            }
            return RecyclerView.INVALID_TYPE;   // 这是第一个HeaderView所占用的空间
        }
        int adjPosition = position - numHeaders;
        int adapterCount = 0;
        if (mAdapter != null) {
            adapterCount = mAdapter.getItemCount();
            if (adjPosition < adapterCount) {
                return mAdapter.getItemViewType(adjPosition);
            }
        }
        return RecyclerView.INVALID_TYPE - 2;   // 说明是Footer的所占用的空间
    }

 

 

2.光在RecyclerWrapAdapter里改还不够,还记得addHeaderView方法的第一行代码mHeaderView.clear();这段代码就从源头上将添加多个HeaderVIew的源头给堵住了,所以,如果我们需要添加多个HeaderView就需要将这段代码删掉。

 

//        mHeaderViews.clear();

 

 

然后再运行下,就可以发现两个HeaderView就成功添加了!



 

下面附上RecyclerWrapAdapter 的源码:

 

 

package com.deltalab.urecommend.adapter.friend_pager;

import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;

import com.deltalab.urecommend.adapter.base.WrapperAdapter;

import java.util.ArrayList;

/**
 * Created by asus on 2016/10/14.
 * 添加了headerView和footerView的布局适配器
 * 模仿ListView里addHeader的HeaderViewListAdapter
 *
 * @author Administrator
 * @time 2016/10/14 16:54
 */
public class RecyclerWrapAdapter extends RecyclerView.Adapter implements WrapperAdapter {

    private RecyclerView.Adapter mAdapter;
    private ArrayList<View> mHeaderViews;
    private ArrayList<View> mFooterViews;
    private int mCurrentPosition = -1;

    static final ArrayList<View> EMPTY_INFO_LIST = new ArrayList<View>();


    public RecyclerWrapAdapter(ArrayList<View> mHeaderViews, ArrayList<View> mFooterViews,
                               RecyclerView.Adapter mAdapter) {
        this.mAdapter = mAdapter;
        if (mHeaderViews == null) {
            this.mHeaderViews = EMPTY_INFO_LIST;
        } else {
            this.mHeaderViews = mHeaderViews;
        }

        if (mFooterViews == null) {
            this.mFooterViews = EMPTY_INFO_LIST;
        } else {
            this.mFooterViews = mFooterViews;
        }
    }

    /**
     * 获取头布局的数量
     *
     * @return
     */
    public int getHeadersCount() {
        return mHeaderViews.size();
    }

    public int getFootersCount() {
        return mFooterViews.size();
    }

    /**
     * 把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例
     * 如果是Header、Footer则使用HeaderViewHolder封装
     * 如果是其他的就不变
     *
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == RecyclerView.INVALID_TYPE) {
            return new HeaderViewHolder(mHeaderViews.get(0));   // 将第一个HeaderView封装
        } else if(viewType == RecyclerView.INVALID_TYPE - 1){
            return new HeaderViewHolder(mHeaderViews.get(1));   // 将第二个HeaderView封装
        } else if (viewType == RecyclerView.INVALID_TYPE - 2) {
            return new HeaderViewHolder(mFooterViews.get(0));   // 将FooterView封装
        }
        return mAdapter.onCreateViewHolder(parent, viewType);
    }

    /**
     * 用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。
     *
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        // Header
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {
            return;
        }
        // Adapter
        int adjPosition = position - numHeaders;
        int adapterCount = 0;
        if (mAdapter != null) {
            adapterCount = mAdapter.getItemCount();
            if (adjPosition < adapterCount) {
                mAdapter.onBindViewHolder(holder, adjPosition);
                return;
            }
        }
    }

    /**
     * 将Header、Footer挂靠到RecyclerView
     *
     * @param recyclerView
     */
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {   // 布局是GridLayoutManager所管理
            final GridLayoutManager gridLayoutManager = (GridLayoutManager) manager;
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    // 如果是Header、Footer的对象则占据spanCount的位置,否则就只占用1个位置
                    return (isHeader(position) || isFooter(position)) ? gridLayoutManager
                            .getSpanCount() : 1;
                }
            });
        }
    }

    /**
     * 判断是否是Header的位置
     * 如果是Header的则返回true否则返回false
     *
     * @param position
     * @return
     */
    public boolean isHeader(int position) {
        return position >= 0 && position < mHeaderViews.size();
    }

    /**
     * 判断是否是Footer的位置
     * 如果是Footer的位置则返回true否则返回false
     *
     * @param position
     * @return
     */
    public boolean isFooter(int position) {
        return position < getItemCount() && position >= getItemCount() - mFooterViews.size();
    }

    @Override
    public int getItemCount() {
        if (mAdapter != null) {
            return getHeadersCount() + getFootersCount() + mAdapter.getItemCount();
        } else {
            return getHeadersCount() + getFootersCount();
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (mCurrentPosition == -1) {
            mCurrentPosition = position;    // 这是第一个HeaderView
        }
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {
            if (position != mCurrentPosition) {  // 这是第二个HeaderView
                return RecyclerView.INVALID_TYPE - 1;   // 这是第二个HeaderView所占用的空间
            }
            return RecyclerView.INVALID_TYPE;   // 这是第一个HeaderView所占用的空间
        }
        int adjPosition = position - numHeaders;
        int adapterCount = 0;
        if (mAdapter != null) {
            adapterCount = mAdapter.getItemCount();
            if (adjPosition < adapterCount) {
                return mAdapter.getItemViewType(adjPosition);
            }
        }
        return RecyclerView.INVALID_TYPE - 2;   // 说明是Footer的所占用的空间
    }

    @Override
    public long getItemId(int position) {
        int numHeaders = getHeadersCount();
        if (mAdapter != null && position >= numHeaders) {
            int adjPosition = position - numHeaders;
            int adapterCount = mAdapter.getItemCount();
            if (adjPosition < adapterCount) {
                return mAdapter.getItemId(adjPosition);     // 不是Header和Footer则返回其itemId
            }
        }
        return -1;
    }

    @Override
    public RecyclerView.Adapter getWrapperAdapter() {
        return mAdapter;
    }

    private static class HeaderViewHolder extends RecyclerView.ViewHolder {

        public HeaderViewHolder(View itemView) {
            super(itemView);
        }
    }
}

 

 

 

  • 大小: 137 KB
1
1
分享到:
评论

相关推荐

    RecyclerView添加header ,添加footer同理

    本教程将详细讲解如何在RecyclerView中添加Header和Footer,这对于构建复杂布局,如添加广告条或者底部操作按钮是非常实用的。 首先,我们需要理解RecyclerView的基本架构。RecyclerView由Adapter和LayoutManager两...

    Android-RecyclerView封装加载更多添加Header和Footer

    以上就是对RecyclerView进行封装,实现加载更多和添加Header、Footer的主要步骤。在LoadMoreRecyclerView-master项目中,你将会看到具体实现这些功能的代码,包括Adapter的实现、滚动监听、UI反馈以及错误处理。通过...

    使用RecyclerView实现带Header和Footer的GridView

    - 创建对应的ViewHolder类,例如HeaderViewHolder、FooterViewHolder和ItemViewHolder,分别处理Header、Footer和列表项的视图绑定。 3. **添加Header和Footer** - 在Adapter的`onCreateViewHolder`方法中,根据`...

    使用RecyclerView添加Header和Footer的方法

    - `getItemViewType(int position)`:根据位置返回viewType,这里需要添加逻辑来区分Header、Footer和数据项。 - `onCreateViewHolder(ViewGroup parent, int viewType)`:根据viewType创建ViewHolder实例,如果...

    recyclerView复用添加头尾及上下刷新源码

    本资源提供了一个实现RecyclerView的全面功能的源码示例,包括添加Header和Footer视图,以及集成下拉刷新和上拉加载更多的功能。 一、RecyclerView基础 RecyclerView的核心在于其适配器(RecyclerView.Adapter)和...

    SectionedRecyclerView可以添加页眉和页脚RecyclerView.rar

    然而,原生的RecyclerView仅提供基本的列表展示功能,无法直接实现页眉(Header)和页脚(Footer)的添加。为了解决这个问题,开发者们通常会采用自定义适配器或者第三方库,如`SectionedRecyclerView`。本篇文章将...

    可添加头部和尾部的 RecyclerView

    本篇将详细讲解如何在RecyclerView中添加头布局(header)和尾布局(footer)。 首先,理解RecyclerView的基本结构。RecyclerView由Adapter、LayoutManager和ViewHolder三部分组成。Adapter是数据源,负责处理数据...

    recyclerView 官方示例

    RecyclerView支持添加Header和Footer,这在实现如下拉刷新、上拉加载更多等功能时非常有用。可以通过在Adapter的构造函数中传递Header和Footer的视图,然后在`getItemViewType()`方法中进行区分。 9. **状态保存和...

    RecyclerView的使用demo

    13. **Header和Footer** 要在RecyclerView中添加头部和尾部,可以利用`addHeaderView()`和`addFooterView()`方法,但需要注意它们不直接支持,需要在Adapter中进行处理。 14. **嵌套滚动** RecyclerView支持嵌套...

    Android-只用recyclerview实现复杂首页布局布局随增减数据动态显示

    4. **Header和Footer**:有时我们需要在列表的顶部或底部添加固定项,可以使用预加载方法在RecyclerView的开始或结束位置添加Header和Footer。 5. **自定义动画**:通过设置ItemAnimator,可以为RecyclerView添加...

    Android-RecyclerView二次封装Adapter支持添加头布局尾部局空布局

    - 尾部布局(Footer Layout)则常用于显示一些附加信息,如加载更多按钮、版权信息等。类似地,我们可以创建一个自定义ViewGroup并将其添加到Adapter的底部。 2. **空布局(Empty View)**: - 当RecyclerView...

    Android-RecyclerView基础写法简单实现

    你可以根据需求添加Header、Footer,或者使用GridLayoutManager、StaggeredGridLayoutManager等其他布局管理器。另外,还可以实现Item点击事件、动画效果以及下拉刷新和上拉加载更多功能。 对于更复杂的需求,例如...

    recyclerview以及各种实用的小demo

    在项目中,还展示了如何添加Header和Footer到RecyclerView。这通常用于显示额外的信息或操作,比如加载更多。可以使用`addHeaderView()`和`addFooterView()`方法,但需要注意它们不直接属于RecyclerView的API,而是...

    4.RecyclerView修改为班级学生分组

    在Android开发中,RecyclerView是一个非常重要的视图组件,它...在实际项目中,你还可以根据需要扩展功能,例如添加Footer、实现滑动加载更多等。记得在编写代码时遵循良好的编程实践,确保代码的可读性和可维护性。

    Recyclerview的使用

    2. 使用Header/Footer功能,可以在列表的开头或结尾添加固定视图。 3. 实现Drag & Drop功能,允许用户重新排列列表项。 4. 使用SnapHelper实现列表项自动吸附效果,如两端对齐、居中对齐等。 5. 结合Paging库实现...

    Android开发-RecyclerView

    3. Header/Footer:在RecyclerView中添加头部或尾部视图。 通过以上讲解,我们了解了RecyclerView的基本概念、使用方法以及一些高级特性。实践中,开发者可以根据需求灵活运用这些知识点,打造高效且用户友好的列表...

    RecyclerView的多种使用方式.rar

    RecyclerView可以通过设置Header和Footer来扩展其功能,比如添加广告栏或加载更多按钮。 6. **嵌套滚动**: RecyclerView可以与其他可滚动视图(如NestedScrollView)实现嵌套滚动,协同处理触摸事件。 7. **...

    Recyclerview-Sample.zip

    RecyclerView还可以添加Header和Footer,以及ItemDecoration来实现分割线。通过addItemDecoration()方法添加自定义的ItemDecoration,可以实现定制的分隔线样式。 7. **点击事件处理** 在ViewHolder中,我们可以...

    RecyclerView

    - Header/Footer支持:可以通过在Adapter的dataList中添加特殊标记来实现头部和尾部的添加。 - 多类型列表:通过在Adapter中判断数据类型并返回不同ViewHolder,可以实现一个列表显示多种视图。 - 动态加载更多:...

    Android studio RecyclerView应用设计

    除了基本的列表项,还可以添加头部视图(header view)和尾部视图(footer view)。这通常通过在适配器中处理逻辑实现,比如在onCreateViewHolder()中返回不同类型的ViewHolder。 十、多视图类型 RecyclerView还...

Global site tag (gtag.js) - Google Analytics