Android-->RecyclerView分组悬浮标题(分割线)

客官先看图:
https://github.com/angcyo/ContactsPicker/blob/master/screenshot/1%E6%9C%88-15-2017%2016-17-46.gif

RecyclerView中实现分组功能, 和 实现分割线 使用的是相同原理. 就是手动绘制信息.

都是继承RecyclerView.ItemDecoration

分割线的实现传送门:http://blog.csdn.net/angcyo/article/details/52829707


1:为分组信息腾出空间

//这个方法就是用来描述是否需要给第二个参数view的上下左右腾出空间.
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    final RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();//布局管理器
    if (!(layoutManager instanceof LinearLayoutManager)) {
        throw new IllegalArgumentException("暂不支持 " + layoutManager.getClass().getSimpleName());
    }

    if (mGroupCallBack == null) {
        return;
    }

    final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
    final int adapterPosition = layoutParams.getViewAdapterPosition();
    if (adapterPosition == 0) {
        //第一个位置, 肯定是有分组信息的
        //我这里需要支持横向和竖向,所以加了方向判断.可以取消掉.
        if (((LinearLayoutManager) layoutManager).getOrientation() == LinearLayoutManager.HORIZONTAL) {
            //为左边腾出空间
            outRect.set(mGroupCallBack.getGroupHeight(), 0, 0, 0);
        } else {
           //为上边腾出空间
            outRect.set(0, mGroupCallBack.getGroupHeight(), 0, 0);
        }
    } else {
        //上一个分组信息
        String preGroupText = mGroupCallBack.getGroupText(adapterPosition - 1);
        //当前的分组信息
        String groupText = mGroupCallBack.getGroupText(adapterPosition);
        if (!TextUtils.equals(preGroupText, groupText)) {
            //如果和上一个分组信息不相等
            if (((LinearLayoutManager) layoutManager).getOrientation() == LinearLayoutManager.HORIZONTAL) {
                outRect.set(mGroupCallBack.getGroupHeight(), 0, 0, 0);
            } else {
                outRect.set(0, mGroupCallBack.getGroupHeight(), 0, 0);
            }
        }
    }
}

2:空间已经给出来了,那么就是绘制你想要的信息了

@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
  if (mGroupCallBack == null) {
      return;
  }

//需要注意的就是, 绘制是从屏幕上布局了多少个子View开始的.
//也就是说, 你并不需要考虑不在屏幕上View的情况.
//通过parent.getChildCount()拿到的就是屏幕上布局了多少个子View的数量
  for (int i = 0; i < parent.getChildCount(); i++) {
      final View view = parent.getChildAt(i);
      final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
      final int adapterPosition = layoutParams.getViewAdapterPosition();
      if (adapterPosition == 0) {
          //第一个位置, 肯定是有分组信息的
          mGroupCallBack.onGroupDraw(c, view, adapterPosition);
      } else {
          //上一个分组信息
          String preGroupText = mGroupCallBack.getGroupText(adapterPosition - 1);
          //当前的分组信息
          String groupText = mGroupCallBack.getGroupText(adapterPosition);
          if (!TextUtils.equals(preGroupText, groupText)) {
              //如果和上一个分组信息不相等
              mGroupCallBack.onGroupDraw(c, view, adapterPosition);
          }
      }
  }
}

通过以上2个方法, 已经可以实现分割线了.

如果需要悬停效果, 那么就继续往下看.

3:悬停效果
onDrawOver方法和onDraw方法完全一样. 只不过名字不一样而已.
你完全可以在onDraw方法中, 实现.
但是官方竟然给了我们这种方法, 而且名字都取得那么好…我们又有什么理由不使用呢?

@Override
 public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
     if (mGroupCallBack == null || parent.getChildCount() <= 0) {
         return;
     }

     boolean isHorizontal = ((LinearLayoutManager) parent.getLayoutManager()).getOrientation() == LinearLayoutManager.HORIZONTAL;

     final View view = parent.getChildAt(0);
     final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
     final int adapterPosition = layoutParams.getViewAdapterPosition();
     if (adapterPosition == 0) {
         //第一个位置, 肯定是有分组信息的
         if ((isHorizontal ? view.getLeft() : view.getTop()) <= 0) {
             mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, 0);
         } else {
             mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, mGroupCallBack.getGroupHeight() - (isHorizontal ? view.getLeft() : view.getTop()));
         }
     } else {
         if (parent.getLayoutManager().getItemCount() > adapterPosition + 1) {
             //下一个分组信息
             String nextGroupText = mGroupCallBack.getGroupText(adapterPosition + 1);
             //当前的分组信息
             String groupText = mGroupCallBack.getGroupText(adapterPosition);

             final View nextView = parent.getChildAt(1);
             if (!TextUtils.equals(nextGroupText, groupText)) {
                 if ((isHorizontal ? nextView.getLeft() : nextView.getTop()) <= 0) {
                     mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, 0);
                 } else {
                     mGroupCallBack.onGroupOverDraw(c, view, adapterPosition,
                             Math.max(0, 2 * mGroupCallBack.getGroupHeight() - (isHorizontal ? nextView.getLeft() : nextView.getTop())));
                 }
             } else {
                 mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, 0);
             }
         } else {
             mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, 0);
         }
     }
 }

开源地址:https://github.com/angcyo/ContactsPicker


至此: 文章就结束了,如有疑问: QQ群 Android:274306954 Swift:399799363 欢迎您的加入.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值