Android RecyclerView添加头部和底部实例详解

Android RecyclerView添加头部和底部实例详解

如果只是想添加头部,可是使用GitHub里面这个项目,它可以为LinearLayoutManager,GridLayoutManager ,StaggeredGridLayoutManager布局的RecyclerView添加header。使用起来也十分简单;
只需将RecyclerViewHeader布局放在RecyclerView的上层。

<FrameLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content">

  <android.support.v7.widget.RecyclerView
    android:id="@+id/recycler"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal|top" />

  <com.bartoszlipinski.recyclerviewheader.RecyclerViewHeader
    android:id="@+id/header"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:layout_gravity="center_horizontal|top">

    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:text="header"/>

  </com.bartoszlipinski.recyclerviewheader.RecyclerViewHeader>

</FrameLayout>

然后获得RecyclerViewHeader对象:

RecyclerViewHeader header = (RecyclerViewHeader) findViewById(R.id.header);

把RecyclerViewHeader赋予RecyclerView

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// set LayoutManager for your RecyclerView
header.attachTo(recyclerView, true);

注意事项

RecyclerViewHeader必须在RecyclerView设置了LayoutManager之后调用。

目前该库适用于LinearLayoutManager,StaggeredGridLayoutManager和GridLayoutManager布局的RecyclerViews。只支持垂直布局LayoutManager。如果你打算在RecyclerView中使用setOnScrollListener(…)方法,确保在setOnScrollListener(…)的attachTo(…)方法之前使用。

当然我们也可以自己写一个添加头部和底部的RecyclerView。它实现的基本原理也是通过getItemViewType方法返回不同的类型来添加头部和底部。

首先我们自定义一个RecyclerView:

public class WrapRecyclerView extends RecyclerView {
  public ArrayList<View> mHeaderViews = new ArrayList<>();
  public ArrayList<View> mFooterViews = new ArrayList<>();
  //添加Adapter
  public Adapter mAdapter;
  public WrapRecyclerView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  public WrapRecyclerView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public WrapRecyclerView(Context context) {
    super(context);
  }
  public void addHeaderView(View view){
    mHeaderViews.clear();
    mHeaderViews.add(view);
    if(mAdapter!=null){
      if(!(mAdapter instanceof RecyclerWrapAdapter)){
        mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,mAdapter);
      }
    }
  }
  public void addFooterView(View view){
    mFooterViews.clear();
    mFooterViews.add(view);
    if(mAdapter!=null){
      if(!(mAdapter instanceof RecyclerWrapAdapter)){
        mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,mAdapter);
      }
    }
  }
  public void setAdapter(Adapter adapter){
    if (mHeaderViews.isEmpty()&&mFooterViews.isEmpty()){

      super.setAdapter(adapter);
    }else {
      adapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,adapter) ;
      super.setAdapter(adapter);
    }
    mAdapter = adapter ;
  }
}

我们会看到我们有一个RecyclerWrapAdapter没有实现,下面我们就来看下RecyclerWrapAdapter,这个也是实现添加头部和尾部的关键。

public class RecyclerWrapAdapter extends RecyclerView.Adapter implements WrapperAdapter{
  private RecyclerView.Adapter mAdapter;

  private ArrayList<View> mHeaderViews;

  private ArrayList<View> mFootViews;
  static final ArrayList<View> EMPTY_INFO_LIST =
      new ArrayList<View>();
  private int mCurrentPosition;
  public RecyclerWrapAdapter(ArrayList<View> mHeaderViews, ArrayList<View> mFootViews, RecyclerView.Adapter mAdapter){
    this.mAdapter = mAdapter;
    if (mHeaderViews == null) {
      this.mHeaderViews = EMPTY_INFO_LIST;
    } else {
      this.mHeaderViews = mHeaderViews;
    }
    if (mFootViews == null) {
      this.mFootViews = EMPTY_INFO_LIST;
    } else {
      this.mFootViews = mFootViews;
    }
  }

  public int getHeadersCount() {
    return mHeaderViews.size();
  }

  public int getFootersCount() {
    return mFootViews.size();
  }
  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == RecyclerView.INVALID_TYPE) {
      return new HeaderViewHolder(mHeaderViews.get(0));
    } else if (viewType == RecyclerView.INVALID_TYPE - 1) {
      return new HeaderViewHolder(mFootViews.get(0));
    }
    return mAdapter.onCreateViewHolder(parent, viewType);
  }

  @Override
  public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    //如果头部不为空,那么我们就要先添加头部,所以我们只要
    //把前面几个position给头部,当position小于头部总数的时候,
    //我们返回头部view。再判断原Adapter 的 count 与当前 position
    // 的差值来比较,是调用原 Adapter 的 getView 方法,还是获取 footView
    // 的 view。
    int numHeaders = getHeadersCount();
    if (position < numHeaders) {
      return;
    }
    int adjPosition = position - numHeaders;
    int adapterCount = 0;
    if (mAdapter != null) {
      adapterCount = mAdapter.getItemCount();
      if (adjPosition < adapterCount) {
        mAdapter.onBindViewHolder(holder, adjPosition);
        return;
      }
    }
  }

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

  @Override
  public RecyclerView.Adapter getWrappedAdapter() {
    return mAdapter;
  }
  @Override
  public int getItemViewType(int position) {
    //增加两个类型
    //RecyclerView.INVALID_TYPE 添加头部
    //RecyclerView.INVALID_TYPE-1 添加尾部
    //如果头部不为空,那么我们就要先添加头部,所以我们只要
    //把前面几个position给头部,当position小于头部总数的时候,
    //我们返回头部类型。再判断原Adapter 的 count 与当前 position
    // 的差值来比较,是调用原 Adapter 的 类型,还是获取 footView
    // 的类型。
    mCurrentPosition = position ;
    int numHeaders = getHeadersCount();
    if(position<numHeaders){
      return RecyclerView.INVALID_TYPE ;
    }
    int adjPosition = position - numHeaders ;
    int adapterCount = 0 ;
    if(mAdapter!=null){
      adapterCount = mAdapter.getItemCount() ;
      if(adjPosition < adapterCount){
        return mAdapter.getItemViewType(adjPosition);
      }
    }
    return RecyclerView.INVALID_TYPE - 1;
  }
  private static class HeaderViewHolder extends RecyclerView.ViewHolder {
    public HeaderViewHolder(View itemView) {
      super(itemView);
    }
  }
}

我们还可以实现一个接口,来调用RecyclerWrapAdapter对象:

public interface WrapperAdapter {

  public RecyclerView.Adapter getWrappedAdapter() ;
}

这样我们就可以把RecyclerView布局改成WrapRecyclerView就可以了,然后调用addHeaderView或者addFooterView就可以添加头部和尾部了。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

时间: 2017-05-30

Android中封装RecyclerView实现添加头部和底部示例代码

前言 我们大家都知道ListView具有添加头部和添加底部的方法,但是RecyclerView并没有这样子的方法.所以RecyclerView是不能添加底部和头部的,但是能不能仿造ListView来实现RecyclerView添加头部和底部呢?答案当然是可行的.本文就来给大家介绍了关于Android封装RecyclerView添加头部和底部的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 首先看下实现的效果: 代码如下: public class WrapMyRecy

Recyclerview添加头布局和尾布局、item点击事件详解

简介: 本篇博客主要包括recyclerview添加多种布局以及添加头布局和尾布局,还有item点击事件 思路: 主要重写Recyclerview.Adapter中的一些方法 1.public int getItemCount()  item熟练  +2(头布局和尾布局) 2.public int getItemViewType(int position)   判断position 设置itemType 3.创建不同的ViewHolder,分别用来加载头布局,正常布局,尾布局 4.public

Android RecyclerView添加头部和底部的方法

如果只是想添加头部,可是使用GitHub里面这个项目,它可以为LinearLayoutManager,GridLayoutManager ,StaggeredGridLayoutManager布局的RecyclerView添加header.使用起来也十分简单: 只需将RecyclerViewHeader布局放在RecyclerView的上层. <FrameLayout android:layout_width="match_parent" android:layout_heigh

Android 中RecyclerView多种item布局的写法(头布局+脚布局)

RecyclerView多个item布局的写法(头布局+脚布局) 上图 github 下载源码 Initial commit第一次提交的代码,为本文内容 以下的为主要代码,看注释即可,比较简单 MainActivity 含上拉加载更多 package com.anew.recyclerviewall; import android.os.Bundle; import android.os.Handler; import android.support.v7.app.AppCompatActivi

Android中RecyclerView的item宽高问题详解

前言 本文主要给大家介绍了关于Android中RecyclerView的item宽高问题的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 在创建viewholder传入的View时,如果不指定其viewgroup,就会出现宽高只包裹显示内容的问题. View view = LayoutInflater.from(context).inflate(R.layout.test_test,null); 上面的做法就会出问题 改成这样就可以正常显示设置的宽高 View vie

Android中RecyclerView实现Item添加和删除的代码示例

本文介绍了Android中RecyclerView实现Item添加和删除的代码示例,分享给大家,具体如下: 先上效果图: RecyclerView简介: RecyclerView用以下两种方式简化了数据的展示和处理: 1. 使用LayoutManager来确定每一个item的排列方式. 2. 为增加和删除项目提供默认的动画效果,也可以自定义. RecyclerView项目结构如下: Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器

Android中RecyclerView点击Item设置事件

在上一篇Android RecylerView入门教程中提到,RecyclerView不再负责Item视图的布局及显示,所以RecyclerView也没有为Item开放OnItemClick等点击事件,这就需要开发者自己实现.博客最下面有Demo程序运行动画. 奉上Demo的Github链接. 在调研过程中,发现有同学修改RecyclerView源码来实现Item的点击监听,但认为这不是一个优雅的解决方案,最终决定在RecyclerView.ViewHolder上做文章. 思路是:因为ViewH

Android中RecyclerView拖拽、侧删功能的实现代码

废话不多说,下面展示一下效果. 这是GridView主文件实现. public class GridViewActivity extends AppCompatActivity { RecyclerView mRecyclerView; List<String> mStringList; RecyclerAdapter mRecyAdapter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { s

Android 中RecyclerView通用适配器的实现

Android 中RecyclerView通用适配器的实现 前言: SDK的5.0版本出来已经N久了,可以说是已经经过许多人的检验了,里面的新控件不能说是非常完美,但也是非常好用了,其中最让我喜爱的就是RecyclerView了,可以完美替代ListView和GridView(除了添加headerview和footview了,网上有许多解决方式.这个下面会以一种简单的方式顺带解决,肯定为大家省心),而且可以代码动态切换这两种布局方式以及瀑布流布局.相关切换方式网上有很多,大家自行搜索,我就不贴连

Android中recyclerView底部添加透明渐变效果

前言 最近实现一个recyclerView透明渐变的效果,遇到了一些坑,尝试了一些方法,这里记录一下. 效果图 图片在上面显示2列,文字在下面显示1列:底部要有个透明渐变的效果,直到完全看不到. gridLayoutManager动态设置列数 大概是分两类,一类以图片为item 一行2个,一类以文字为item 一行一个. 这个第一反应是用viewType去区分图片类型,但是由于起初不知道gridLayout可以动态列数.就在上面两列,下面一列上为难起来了. 如果统一用一列吧,那就把两个image

Android 中RecyclerView顶部刷新实现详解

Android 中RecyclerView顶部刷新实现详解 1. RecyclerView顶部刷新的原理 RecyclerView顶部刷新的实现通常都是在RecyclerView外部再包裹一层布局.在这个外层布局中,还包含一个自定义的View,作为顶部刷新时的指示View.也就是说,外层布局中包含两个child,一个顶部刷新View,一个RecyclerView,顶部刷新View默认是隐藏不可见的.在外层布局中对滑动事件进行处理,当RecyclerView滑动到顶部并继续下滑的时候,根据滑动的距

Android中RecyclerView实现横向滑动代码

RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好.本文给大家介绍Android中RecyclerView实现横向滑动代码,一起看看吧. android.support.v7.widget.RecyclerView 功能:RecyclerView横向滑动 控件:<android.support.v7.widget.RecyclerView /> Java类:RecyclerView.GalleryAdap

Android中ListView的item点击没有反应的解决方法

如果stu_item.xml里面包括button或者checkbox等控件,默认情况下list的item会失去焦点,导致无法响应item的事件,最常用的解决办法是在stu_item.xml的布局文件中设置descendantFocusability属性. 该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系. 属性的值有三种: beforeDescendants:viewgroup会优先其子类控件而获取到焦点 afterDescendants:viewgroup只有